From xuwei5 at hisilicon.com  Mon Jun  1 03:21:40 2015
From: xuwei5 at hisilicon.com (Wei Xu)
Date: Mon, 1 Jun 2015 11:21:40 +0100
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
Message-ID: <556C3234.2030805@hisilicon.com>



On 5/19/2015 5:12 PM, Russell King wrote:
> All ARMv5 and older CPUs invalidate their caches in the early assembly
> setup function, prior to enabling the MMU.  This is because the L1
> cache should not contain any data relevant to the execution of the
> kernel at this point; all data should have been flushed out to memory.
> 
> This requirement should also be true for ARMv6 and ARMv7 CPUs - indeed,
> these typically do not search their caches when caching is disabled (as
> it needs to be when the MMU is disabled) so this change should be safe.
> 
> ARMv7 allows there to be CPUs which search their caches while caching is
> disabled, and it's permitted that the cache is uninitialised at boot;
> for these, the architecture reference manual requires that an
> implementation specific code sequence is used immediately after reset
> to ensure that the cache is placed into a sane state.  Such
> functionality is definitely outside the remit of the Linux kernel, and
> must be done by the SoC's firmware before _any_ CPU gets to the Linux
> kernel.
> 
> Changing the data cache clean+invalidate to a mere invalidate allows us
> to get rid of a lot of platform specific hacks around this issue for
> their secondary CPU bringup paths - some of which were buggy.
> 
> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> ---

Hi Russell,

[...]
>  arch/arm/mach-hisi/Makefile           |  2 +-
>  arch/arm/mach-hisi/core.h             |  1 -
>  arch/arm/mach-hisi/headsmp.S          | 16 ----------------
>  arch/arm/mach-hisi/platsmp.c          |  4 ++--
[...]

Sorry for the late reply.
For Hisilicon:
    - hip01/ca9x2
    - hix5hd2/dkb

Tested-by: Wei Xu <xuwei5 at hisilicon.com>

Thanks!

Best Regards,
Wei



From geert at linux-m68k.org  Mon Jun  1 03:41:01 2015
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 1 Jun 2015 12:41:01 +0200
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
Message-ID: <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>

On Fri, May 22, 2015 at 9:36 AM, Geert Uytterhoeven
<geert at linux-m68k.org> wrote:
> On Tue, May 19, 2015 at 6:12 PM, Russell King
> <rmk+kernel at arm.linux.org.uk> wrote:
>> All ARMv5 and older CPUs invalidate their caches in the early assembly
>> setup function, prior to enabling the MMU.  This is because the L1
>> cache should not contain any data relevant to the execution of the
>> kernel at this point; all data should have been flushed out to memory.
>>
>> This requirement should also be true for ARMv6 and ARMv7 CPUs - indeed,
>> these typically do not search their caches when caching is disabled (as
>> it needs to be when the MMU is disabled) so this change should be safe.
>>
>> ARMv7 allows there to be CPUs which search their caches while caching is
>> disabled, and it's permitted that the cache is uninitialised at boot;
>> for these, the architecture reference manual requires that an
>> implementation specific code sequence is used immediately after reset
>> to ensure that the cache is placed into a sane state.  Such
>> functionality is definitely outside the remit of the Linux kernel, and
>> must be done by the SoC's firmware before _any_ CPU gets to the Linux
>> kernel.
>>
>> Changing the data cache clean+invalidate to a mere invalidate allows us
>> to get rid of a lot of platform specific hacks around this issue for
>> their secondary CPU bringup paths - some of which were buggy.
>>
>> Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
>
> For various shmobile:
>   - sh73a0/kzm9g
>   - r8a7740/armadillo
>   - r8a73a4/ape6evm
>   - r8a7791/koelsch
>
> Tested-by: Geert Uytterhoeven <geert+renesas at glider.be>

FWIW, I have the feeling this has a slight influence on boot reliability on
two of my boards:
  - r8a7740/armadillo, which is known to suffer from a cache-related bug in
    its bootloader, seems to have a higher change of booting successfully on
    cold boot,
  - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
    seems to have a lower chance of booting successfully.

No time to spend all week turning this into a statistical significant test
project... The reset button is my friend...

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From linux at arm.linux.org.uk  Mon Jun  1 03:53:20 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 1 Jun 2015 11:53:20 +0100
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
Message-ID: <20150601105319.GQ2067@n2100.arm.linux.org.uk>

On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
> FWIW, I have the feeling this has a slight influence on boot reliability on
> two of my boards:
>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
>     its bootloader, seems to have a higher change of booting successfully on
>     cold boot,
>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
>     seems to have a lower chance of booting successfully.
> 
> No time to spend all week turning this into a statistical significant test
> project... The reset button is my friend...

Damn it, you sent this right after I merged and pushed out this change in
my for-arm-soc branch, and was just about to send it to the arm-soc people.
What excellent timing you have. :)

What happens on the kzm9g if you revert the mach-shmobile changes?

For armadillo, do you use the decompressor?  That should be doing all the
cache cleaning already, prior to the kernel being entered.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From geert at linux-m68k.org  Mon Jun  1 04:50:19 2015
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Mon, 1 Jun 2015 13:50:19 +0200
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <20150601105319.GQ2067@n2100.arm.linux.org.uk>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
Message-ID: <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>

Hi Russell,

On Mon, Jun 1, 2015 at 12:53 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
>> FWIW, I have the feeling this has a slight influence on boot reliability on
>> two of my boards:
>>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
>>     its bootloader, seems to have a higher change of booting successfully on
>>     cold boot,
>>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
>>     seems to have a lower chance of booting successfully.
>>
>> No time to spend all week turning this into a statistical significant test
>> project... The reset button is my friend...
>
> Damn it, you sent this right after I merged and pushed out this change in
> my for-arm-soc branch, and was just about to send it to the arm-soc people.
> What excellent timing you have. :)

Don't worry, I didn't send that email to make you postpone this change.
Giving the fuzziness of reproduction, and the flakiness (esp. on Armadillo)
of the boot loader, and these are old SoCs, please go ahead.

> What happens on the kzm9g if you revert the mach-shmobile changes?

Seems to make no difference.

> For armadillo, do you use the decompressor?  That should be doing all the
> cache cleaning already, prior to the kernel being entered.

I think so.

Corruption pattern ranges from lock up, over "Error: unrecognized/unsupported
machine ID", to booting almost completely, but lacking a few devices due to
a corrupted DTB. Been like that as long as I remember, i.e. since I got the
board ca. 1 year ago. Boots fine (100%) with kexec.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From heiko at sntech.de  Tue Jun  2 07:41:45 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 02 Jun 2015 16:41:45 +0200
Subject: [PATCH] drm/rockchip: only call drm_fb_helper_hotplug_event if
 fb_helper present
Message-ID: <1895627.zroongJmBp@diego>

Add a check for the presence of fb_helper to rockchip_drm_output_poll_changed()
to only call drm_fb_helper_hotplug_event if there is actually a fb_helper
available. Without this check I see NULL pointer dereferences when the
hdmi hotplug irq fires before the fb_helper got initialized.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
Fix to variant as seen on at least Exynos, Armada and Omap

 drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 77d5289..002645b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -162,7 +162,8 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
 	struct rockchip_drm_private *private = dev->dev_private;
 	struct drm_fb_helper *fb_helper = &private->fbdev_helper;
 
-	drm_fb_helper_hotplug_event(fb_helper);
+	if (fb_helper)
+		drm_fb_helper_hotplug_event(fb_helper);
 }
 
 static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
-- 
2.1.4




From mark.yao at rock-chips.com  Tue Jun  2 20:40:33 2015
From: mark.yao at rock-chips.com (Mark yao)
Date: Wed, 03 Jun 2015 11:40:33 +0800
Subject: [PATCH v2] drm/rockchip: Add BGR formats to VOP
In-Reply-To: <CAAFQd5A1HTV+LdkTSeQrjX=MpQEseY9-NF5PySJq_B+rrmTMkw@mail.gmail.com>
References: <1431341739-12523-1-git-send-email-tfiga@chromium.org>
 <CAAFQd5A1HTV+LdkTSeQrjX=MpQEseY9-NF5PySJq_B+rrmTMkw@mail.gmail.com>
Message-ID: <556E7731.6020403@rock-chips.com>

On 2015?05?30? 02:56, Tomasz Figa wrote:
> On Mon, May 11, 2015 at 7:55 PM, Tomasz Figa <tfiga at chromium.org> wrote:
>> VOP can support BGR formats in all windows thanks to red/blue swap option
>> provided in WINx_CTRL0 registers. This patch enables support for
>> ABGR8888, XBGR8888, BGR888 and BGR565 formats by using this feature.
>>
>> Signed-off-by: Tomasz Figa <tfiga at chromium.org>
>> ---
>>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +++++++++++++++++++++++++++++
>>   1 file changed, 33 insertions(+)
>>
>> Changes since v1:
>> (https://patchwork.kernel.org/patch/6369531/)
>>   - Fixed register addresses for win2/3 and hwc (reported by Mark Yao).
> Gentle ping.
Applied to my drm-next:-)
> Best regards,
> Tomasz
>
>
>


-- 
?ark Yao




From mark.yao at rock-chips.com  Tue Jun  2 20:41:14 2015
From: mark.yao at rock-chips.com (Mark yao)
Date: Wed, 03 Jun 2015 11:41:14 +0800
Subject: [PATCH] drm/rockchip: only call drm_fb_helper_hotplug_event if
 fb_helper present
In-Reply-To: <1895627.zroongJmBp@diego>
References: <1895627.zroongJmBp@diego>
Message-ID: <556E775A.1030009@rock-chips.com>

On 2015?06?02? 22:41, Heiko St?bner wrote:
> Add a check for the presence of fb_helper to rockchip_drm_output_poll_changed()
> to only call drm_fb_helper_hotplug_event if there is actually a fb_helper
> available. Without this check I see NULL pointer dereferences when the
> hdmi hotplug irq fires before the fb_helper got initialized.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
> Fix to variant as seen on at least Exynos, Armada and Omap
>
>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> index 77d5289..002645b 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> @@ -162,7 +162,8 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
>   	struct rockchip_drm_private *private = dev->dev_private;
>   	struct drm_fb_helper *fb_helper = &private->fbdev_helper;
>   
> -	drm_fb_helper_hotplug_event(fb_helper);
> +	if (fb_helper)
> +		drm_fb_helper_hotplug_event(fb_helper);
Thanks for the fix, Applied to my drm-next
>   }
>   
>   static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {


-- 
?ark Yao




From jiang.liu at linux.intel.com  Wed Jun  3 21:13:44 2015
From: jiang.liu at linux.intel.com (Jiang Liu)
Date: Thu,  4 Jun 2015 12:13:44 +0800
Subject: [RFT v2 34/48] pinctrl: Prepare for killing the first parameter 'irq'
 of irq_flow_handler_t
In-Reply-To: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <1433391238-19471-35-git-send-email-jiang.liu@linux.intel.com>

Change irq flow handler to prepare for killing the first parameter 'irq'
of irq_flow_handler_t.

Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
---
 drivers/pinctrl/pinctrl-amd.c         |    6 ++++--
 drivers/pinctrl/pinctrl-coh901.c      |    3 ++-
 drivers/pinctrl/pinctrl-rockchip.c    |    4 ++--
 drivers/pinctrl/sirf/pinctrl-sirf.c   |    3 ++-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c |    3 ++-
 5 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 639cd77c1fbb..31e206613814 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -492,7 +492,7 @@ static struct irq_chip amd_gpio_irqchip = {
 	.irq_set_type = amd_gpio_irq_set_type,
 };
 
-static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
 {
 	u32 i;
 	u32 off;
@@ -527,6 +527,8 @@ static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 						(off * 4 + i) * 4);
 				if ((pin_reg & BIT(INTERRUPT_STS_OFF)) ||
 					(pin_reg & BIT(WAKE_STS_OFF))) {
+					unsigned int irq;
+
 					irq = irq_find_mapping(gc->irqdomain,
 								off * 4 + i);
 					generic_handle_irq(irq);
@@ -540,7 +542,7 @@ static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	}
 
 	if (handled == 0)
-		handle_bad_irq(irq, desc);
+		handle_bad_irq(__irq, desc);
 
 	spin_lock_irqsave(&gpio_dev->lock, flags);
 	reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 9579442a221d..3731cc67a88b 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -519,8 +519,9 @@ static struct irq_chip u300_gpio_irqchip = {
 	.irq_set_type		= u300_gpio_irq_type,
 };
 
-static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void u300_gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
 {
+	unsigned int irq = irq_desc_get_irq(desc);
 	struct irq_chip *parent_chip = irq_desc_get_chip(desc);
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct u300_gpio *gpio = to_u300_gpio(chip);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 97a4a3dddb30..1fff71221d83 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1394,7 +1394,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
  * Interrupt handling
  */
 
-static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
+static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
@@ -1407,7 +1407,7 @@ static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
 	pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS);
 
 	while (pend) {
-		unsigned int virq;
+		unsigned int virq, irq;
 
 		irq = __ffs(pend);
 		pend &= ~BIT(irq);
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 46cafde08ebf..89792e12d744 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -545,8 +545,9 @@ static struct irq_chip sirfsoc_irq_chip = {
 	.irq_set_type = sirfsoc_gpio_irq_type,
 };
 
-static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
+static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
 {
+	unsigned int irq = irq_desc_get_irq(desc);
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct sirfsoc_gpio_chip *sgpio = to_sirfsoc_gpio(gc);
 	struct sirfsoc_gpio_bank *bank;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 563cec6dc24e..ace032681d82 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -709,8 +709,9 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
 			  IRQCHIP_EOI_IF_HANDLED,
 };
 
-static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
+static void sunxi_pinctrl_irq_handler(unsigned __irq, struct irq_desc *desc)
 {
+	unsigned int irq = irq_desc_get_irq(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
 	unsigned long bank, reg, val;
-- 
1.7.10.4



From sboyd at codeaurora.org  Thu Jun  4 14:27:25 2015
From: sboyd at codeaurora.org (Stephen Boyd)
Date: Thu, 4 Jun 2015 14:27:25 -0700
Subject: [PATCH] clk: make several parent names const
In-Reply-To: <1432802751-6397-1-git-send-email-u.kleine-koenig@pengutronix.de>
References: <1432802751-6397-1-git-send-email-u.kleine-koenig@pengutronix.de>
Message-ID: <20150604212725.GR676@codeaurora.org>

On 05/28, Uwe Kleine-K?nig wrote:
> Since commit 2893c379461a ("clk: make strings in parent name arrays
> const") the name of parent clocks can be const. So add more const in
> several clock drivers.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---

Applied to clk-next

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


From wxt at rock-chips.com  Thu Jun  4 21:47:54 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 12:47:54 +0800
Subject: [PATCH 0/3]     ARM: rockchip: fix the SMP
Message-ID: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>

    Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WIF state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Thu Jun  4 21:47:55 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 12:47:55 +0800
Subject: [PATCH 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433479677-18086-2-git-send-email-wxt@rock-chips.com>

In general, the correct flow is:

cpu off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))

cpu on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    reset_control_deassert

You can repro it with bringing CPU up and down.
Says:(test scripts)

    cd /sys/devices/system/cpu/
    for i in $(seq 1000); do
    echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000" ]]; do
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
[34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
[34466.186824] Disabling non-boot CPUs ...
[34466.187509] CPU1: shutdown
[34466.188672] CPU2: shutdown
[34473.736627] Kernel panic - not syncing: Watchdog detected hard LOCKUP on cpu 0
[34473.736646] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 3.14.0 #1
[34473.736687] [<c010dfb0>] (unwind_backtrace) from [<c010a460>] (show_stack+0x20/0x24)
[34473.736711] [<c010a460>] (show_stack) from [<c0630670>] (dump_stack+0x70/0x8c)
[34473.736731] [<c0630670>] (dump_stack) from [<c062fa0c>] (panic+0xa8/0x1fc)
[34473.736754] [<c062fa0c>] (panic) from [<c0191efc>] (watchdog_timer_fn+0x234/0x26c)
[34473.736777] [<c0191efc>] (watchdog_timer_fn) from [<c014103c>] (__run_hrtimer+0x118/0x1e0)
[34473.736797] [<c014103c>] (__run_hrtimer) from [<c0141c04>] (hrtimer_interrupt+0x148/0x2a0)
[34473.736820] [<c0141c04>] (hrtimer_interrupt) from [<c04d9994>] (arch_timer_handler_phys+0x38/0x48)
[34473.736844] [<c04d9994>] (arch_timer_handler_phys) from [<c016acc4>] (handle_percpu_devid_irq+0xb8/0x124)
[34473.736867] [<c016acc4>] (handle_percpu_devid_irq) from [<c0166a30>] (generic_handle_irq+0x30/0x40)
[34473.736887] [<c0166a30>] (generic_handle_irq) from [<c0166d28>] (__handle_domain_irq+0x8c/0xb0)
[34473.736905] [<c0166d28>] (__handle_domain_irq) from [<c01003a0>] (gic_handle_irq+0x48/0x6c)
[34473.736922] [<c01003a0>] (gic_handle_irq) from [<c010b040>] (__irq_svc+0x40/0x50)
[34473.736936] Exception stack(0xee127f70 to 0xee127fb8)
[34473.736948] 7f60:                                     ffffffed 00000000 2dd6d000 00000000
[34473.736964] 7f80: ee126000 00000015 c0b46bac c0b46bac 0000406a 410fc0d1 00000000 ee127fc4
[34473.736979] 7fa0: ee127fb8 ee127fb8 c0107038 c010703c 600f0013 ffffffff
[34473.736995] [<c010b040>] (__irq_svc) from [<c010703c>] (arch_cpu_idle+0x40/0x48)
[34473.737013] [<c010703c>] (arch_cpu_idle) from [<c0166978>] (cpu_startup_entry+0x170/0x1d0)
[34473.737031] [<c0166978>] (cpu_startup_entry) from [<c010c254>] (secondary_start_kernel+0x138/0x160)
[34473.737059] [<c010c254>] (secondary_start_kernel) from [<00100464>] (0x100464)
[34474.903740] SMP: failed to stop secondary CPUs
[34476.099964] SMP: failed to stop secondary CPUs
...

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..1230d3d 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -88,20 +88,17 @@ static int pmu_set_power_domain(int pd, bool on)
 			return PTR_ERR(rstc);
 		}
 
-		if (on)
+		if (on) {
+			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
 			reset_control_deassert(rstc);
-		else
+		} else {
 			reset_control_assert(rstc);
+			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		}
 
 		reset_control_put(rstc);
 	}
 
-	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
-	if (ret < 0) {
-		pr_err("%s: could not update power domain\n", __func__);
-		return ret;
-	}
-
 	ret = -1;
 	while (ret != on) {
 		ret = pmu_power_domain_is_on(pd);
-- 
1.9.1



From wxt at rock-chips.com  Thu Jun  4 21:47:56 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 12:47:56 +0800
Subject: [PATCH 2/3] ARM: rockchip: ensure CPU to enter WIF state
In-Reply-To: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433479677-18086-3-git-send-email-wxt@rock-chips.com>

In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
WFI/WFE state.
we can delay 1ms to ensure the CPU enter WFI state.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 1230d3d..978c357 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -316,6 +316,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Thu Jun  4 21:47:57 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 12:47:57 +0800
Subject: [PATCH 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433479677-18086-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f arch/arm/mach-rockchip/platsmp.c

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 978c357..7eea805 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -104,7 +104,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -128,7 +128,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -147,7 +147,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		udelay(10);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -326,7 +326,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
-- 
1.9.1



From kever.yang at rock-chips.com  Thu Jun  4 23:32:27 2015
From: kever.yang at rock-chips.com (Kever Yang)
Date: Fri, 05 Jun 2015 14:32:27 +0800
Subject: [PATCH 2/3] ARM: rockchip: ensure CPU to enter WIF state
In-Reply-To: <1433479677-18086-3-git-send-email-wxt@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
 <1433479677-18086-3-git-send-email-wxt@rock-chips.com>
Message-ID: <5571427B.1040406@rock-chips.com>

Hi Caesar,

Subject typo WIF/WFI.

On 06/05/2015 12:47 PM, Caesar Wang wrote:
> In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
> WFI/WFE state.
> we can delay 1ms to ensure the CPU enter WFI state.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
>
>   arch/arm/mach-rockchip/platsmp.c | 3 +++
>   1 file changed, 3 insertions(+)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 1230d3d..978c357 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -316,6 +316,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
>   #ifdef CONFIG_HOTPLUG_CPU
>   static int rockchip_cpu_kill(unsigned int cpu)
>   {
> +	/* ensure CPU can enter the WFI/WFE state */
> +	mdelay(1);
> +
Does it matter if core is not in WFI state when we want to power down it?

Thanks,
- Kever
>   	pmu_set_power_domain(0 + cpu, false);
>   	return 1;
>   }



From wxt at rock-chips.com  Thu Jun  4 23:58:18 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 05 Jun 2015 14:58:18 +0800
Subject: [PATCH 2/3] ARM: rockchip: ensure CPU to enter WIF state
In-Reply-To: <5571427B.1040406@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
 <1433479677-18086-3-git-send-email-wxt@rock-chips.com>
 <5571427B.1040406@rock-chips.com>
Message-ID: <5571488A.5040609@rock-chips.com>



? 2015?06?05? 14:32, Kever Yang ??:
> Hi Caesar,
>
> Subject typo WIF/WFI.
OK

>
> On 06/05/2015 12:47 PM, Caesar Wang wrote:
>> In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
>> WFI/WFE state.
>> we can delay 1ms to ensure the CPU enter WFI state.
>>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> ---
>>
>>   arch/arm/mach-rockchip/platsmp.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/arm/mach-rockchip/platsmp.c 
>> b/arch/arm/mach-rockchip/platsmp.c
>> index 1230d3d..978c357 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -316,6 +316,9 @@ static void __init 
>> rockchip_smp_prepare_cpus(unsigned int max_cpus)
>>   #ifdef CONFIG_HOTPLUG_CPU
>>   static int rockchip_cpu_kill(unsigned int cpu)
>>   {
>> +    /* ensure CPU can enter the WFI/WFE state */
>> +    mdelay(1);
>> +
> Does it matter if core is not in WFI state when we want to power down it?
>
As HuangTao suggestion,

In gerenal, we need enter the WFI state when core power down, right?
That will be more better if the hardware can judge the state.

Anyway, we can delay 1ms or more to wait the WFI state.
That should be more better, right?

> Thanks,
> - Kever
>>       pmu_set_power_domain(0 + cpu, false);
>>       return 1;
>>   }
>
>
>
>




From heiko at sntech.de  Fri Jun  5 01:45:50 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 10:45:50 +0200
Subject: [PATCH 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433479677-18086-2-git-send-email-wxt@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
 <1433479677-18086-2-git-send-email-wxt@rock-chips.com>
Message-ID: <1604172.FydsUUUXNY@diego>

Hi Caesar,


thanks for investigating this.

Am Freitag, 5. Juni 2015, 12:47:55 schrieb Caesar Wang:
> In general, the correct flow is:
> 
> cpu off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
> 
> cpu on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     reset_control_deassert
> 
> You can repro it with bringing CPU up and down.
> Says:(test scripts)
> 
>     cd /sys/devices/system/cpu/
>     for i in $(seq 1000); do
>     echo "================= $i ============"
>         for j in $(seq 100); do
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> cpu3/online)" != "000" ]]; do echo 0 > cpu1/online
>                 echo 0 > cpu2/online
>                 echo 0 > cpu3/online
>             done
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> cpu3/online)" != "111" ]]; do echo 1 > cpu1/online
>                 echo 1 > cpu2/online
>                 echo 1 > cpu3/online
>             done
>         done
>     done
> 
> The following is reproducile log:
> [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
> [34466.186824] Disabling non-boot CPUs ...
> [34466.187509] CPU1: shutdown
> [34466.188672] CPU2: shutdown
> [34473.736627] Kernel panic - not syncing: Watchdog detected hard LOCKUP on
> cpu 0 [34473.736646] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 3.14.0 #1
> [34473.736687] [<c010dfb0>] (unwind_backtrace) from [<c010a460>]
> (show_stack+0x20/0x24) [34473.736711] [<c010a460>] (show_stack) from
> [<c0630670>] (dump_stack+0x70/0x8c) [34473.736731] [<c0630670>]
> (dump_stack) from [<c062fa0c>] (panic+0xa8/0x1fc) [34473.736754]
> [<c062fa0c>] (panic) from [<c0191efc>] (watchdog_timer_fn+0x234/0x26c)
> [34473.736777] [<c0191efc>] (watchdog_timer_fn) from [<c014103c>]
> (__run_hrtimer+0x118/0x1e0) [34473.736797] [<c014103c>] (__run_hrtimer)
> from [<c0141c04>] (hrtimer_interrupt+0x148/0x2a0) [34473.736820]
> [<c0141c04>] (hrtimer_interrupt) from [<c04d9994>]
> (arch_timer_handler_phys+0x38/0x48) [34473.736844] [<c04d9994>]
> (arch_timer_handler_phys) from [<c016acc4>]
> (handle_percpu_devid_irq+0xb8/0x124) [34473.736867] [<c016acc4>]
> (handle_percpu_devid_irq) from [<c0166a30>] (generic_handle_irq+0x30/0x40)
> [34473.736887] [<c0166a30>] (generic_handle_irq) from [<c0166d28>]
> (__handle_domain_irq+0x8c/0xb0) [34473.736905] [<c0166d28>]
> (__handle_domain_irq) from [<c01003a0>] (gic_handle_irq+0x48/0x6c)
> [34473.736922] [<c01003a0>] (gic_handle_irq) from [<c010b040>]
> (__irq_svc+0x40/0x50) [34473.736936] Exception stack(0xee127f70 to
> 0xee127fb8)
> [34473.736948] 7f60:                                     ffffffed 00000000
> 2dd6d000 00000000 [34473.736964] 7f80: ee126000 00000015 c0b46bac c0b46bac
> 0000406a 410fc0d1 00000000 ee127fc4 [34473.736979] 7fa0: ee127fb8 ee127fb8
> c0107038 c010703c 600f0013 ffffffff [34473.736995] [<c010b040>] (__irq_svc)
> from [<c010703c>] (arch_cpu_idle+0x40/0x48) [34473.737013] [<c010703c>]
> (arch_cpu_idle) from [<c0166978>] (cpu_startup_entry+0x170/0x1d0)
> [34473.737031] [<c0166978>] (cpu_startup_entry) from [<c010c254>]
> (secondary_start_kernel+0x138/0x160) [34473.737059] [<c010c254>]
> (secondary_start_kernel) from [<00100464>] (0x100464) [34474.903740] SMP:
> failed to stop secondary CPUs
> [34476.099964] SMP: failed to stop secondary CPUs
> ...
> 
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
> 
>  arch/arm/mach-rockchip/platsmp.c | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/mach-rockchip/platsmp.c
> b/arch/arm/mach-rockchip/platsmp.c index 5b4ca3c..1230d3d 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -88,20 +88,17 @@ static int pmu_set_power_domain(int pd, bool on)
>  			return PTR_ERR(rstc);
>  		}
> 
> -		if (on)
> +		if (on) {
> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>  			reset_control_deassert(rstc);
> -		else
> +		} else {
>  			reset_control_assert(rstc);
> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> +		}

you're loosing the return value of regmap_update_bits here, I guess it should 
look like below?

		if (on) {
			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
			if (ret < 0) {
				pr_err("%s: could not update power domain\n", __func__);
		  		reset_control_put(rstc);
				return ret;
			}

			reset_control_deassert(rstc);
		} else {
			reset_control_assert(rstc);

			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
			if (ret < 0) {
				pr_err("%s: could not update power domain\n", __func__);
		  		reset_control_put(rstc);
				return ret;
			}
		}


> 
>  		reset_control_put(rstc);
>  	}
> 
> -	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> -	if (ret < 0) {
> -		pr_err("%s: could not update power domain\n", __func__);
> -		return ret;
> -	}
> -
>  	ret = -1;
>  	while (ret != on) {
>  		ret = pmu_power_domain_is_on(pd);

second question - with this patch, what happens actually is

 cpu off:
     reset_control_assert
     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
     wait_for_power_domain_to_turn_off
 
 cpu on:
     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
     reset_control_deassert
     wait_for_power_domain_to_turn_on

So shouldn't the deassertion of the reset happen after the powerdomain 
sucessfull turned on? Like

 cpu on:
     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
     wait_for_power_domain_to_turn_on
     reset_control_deassert



From linus.walleij at linaro.org  Mon Jun  1 05:46:34 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Mon, 1 Jun 2015 14:46:34 +0200
Subject: [RFC v1 06/25] pinctrl: Use irq_desc_get_xxx() to avoid redundant
 lookup of irq_desc
In-Reply-To: <1432116013-25902-7-git-send-email-jiang.liu@linux.intel.com>
References: <1432116013-25902-1-git-send-email-jiang.liu@linux.intel.com>
 <1432116013-25902-7-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CACRpkdazXuq7WZZPiObRNFBTokazUN9yisU7VNobS4ezgZTHJw@mail.gmail.com>

On Wed, May 20, 2015 at 11:59 AM, Jiang Liu <jiang.liu at linux.intel.com> wrote:

> Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc while we
> already have a pointer to corresponding irq_desc.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Are there dependencies on this patch or can I just apply it
directly to the GPIO tree?

Yours,
Linus Walleij


From jiang.liu at linux.intel.com  Wed Jun  3 21:13:16 2015
From: jiang.liu at linux.intel.com (Jiang Liu)
Date: Thu,  4 Jun 2015 12:13:16 +0800
Subject: [RFT v2 06/48] pinctrl: Use irq_desc_get_xxx() to avoid redundant
 lookup of irq_desc
In-Reply-To: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>

Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc while we
already have a pointer to corresponding irq_desc.

Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/pinctrl/intel/pinctrl-cherryview.c    |    2 +-
 drivers/pinctrl/intel/pinctrl-intel.c         |    2 +-
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    4 ++--
 drivers/pinctrl/nomadik/pinctrl-nomadik.c     |   12 +++++-------
 drivers/pinctrl/pinctrl-amd.c                 |    2 +-
 drivers/pinctrl/pinctrl-at91.c                |    2 +-
 drivers/pinctrl/pinctrl-coh901.c              |    4 ++--
 drivers/pinctrl/pinctrl-rockchip.c            |    4 ++--
 drivers/pinctrl/pinctrl-single.c              |    2 +-
 drivers/pinctrl/pinctrl-st.c                  |    6 +++---
 drivers/pinctrl/qcom/pinctrl-msm.c            |    2 +-
 drivers/pinctrl/samsung/pinctrl-exynos.c      |    8 ++++----
 drivers/pinctrl/samsung/pinctrl-s3c24xx.c     |   18 +++++++++---------
 drivers/pinctrl/samsung/pinctrl-s3c64xx.c     |   22 ++++++++++------------
 drivers/pinctrl/sirf/pinctrl-sirf.c           |    2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         |    4 ++--
 16 files changed, 46 insertions(+), 50 deletions(-)

diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 82f691eeeec4..878e798bcb56 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1368,7 +1368,7 @@ static void chv_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned long pending;
 	u32 intr_line;
 
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 00768e53deec..a40681097402 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -840,7 +840,7 @@ static void intel_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int i;
 
 	chained_irq_enter(chip, desc);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 474812e2b0cb..fd05ca6125b0 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1018,8 +1018,8 @@ mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
 
 static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct mtk_pinctrl *pctl = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
 	unsigned int status, eint_num;
 	int offset, index, virq;
 	const struct mtk_eint_offsets *eint_offsets =
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index a6a22054c0ba..902f53b855bf 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -854,10 +854,9 @@ static struct irq_chip nmk_gpio_irq_chip = {
 	.flags		= IRQCHIP_MASK_ON_SUSPEND,
 };
 
-static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
-				   u32 status)
+static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status)
 {
-	struct irq_chip *host_chip = irq_get_chip(irq);
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 
 	chained_irq_enter(host_chip, desc);
@@ -882,17 +881,16 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	status = readl(nmk_chip->addr + NMK_GPIO_IS);
 	clk_disable(nmk_chip->clk);
 
-	__nmk_gpio_irq_handler(irq, desc, status);
+	__nmk_gpio_irq_handler(desc, status);
 }
 
-static void nmk_gpio_latent_irq_handler(unsigned int irq,
-					   struct irq_desc *desc)
+static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
 	u32 status = nmk_chip->get_latent_status(nmk_chip->bank);
 
-	__nmk_gpio_irq_handler(irq, desc, status);
+	__nmk_gpio_irq_handler(desc, status);
 }
 
 /* I/O Functions */
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 7de3b64bf142..639cd77c1fbb 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -501,7 +501,7 @@ static void amd_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	u64 reg64;
 	int handled = 0;
 	unsigned long flags;
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct amd_gpio *gpio_dev = to_amd_gpio(gc);
 
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 2f797cb7e205..92d5f9ec1cce 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1581,7 +1581,7 @@ static struct irq_chip gpio_irqchip = {
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
 	struct at91_gpio_chip *at91_gpio = container_of(gpio_chip,
 					   struct at91_gpio_chip, chip);
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 29cbbab8c3a6..9579442a221d 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -521,8 +521,8 @@ static struct irq_chip u300_gpio_irqchip = {
 
 static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct irq_chip *parent_chip = irq_get_chip(irq);
-	struct gpio_chip *chip = irq_get_handler_data(irq);
+	struct irq_chip *parent_chip = irq_desc_get_chip(desc);
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct u300_gpio *gpio = to_u300_gpio(chip);
 	struct u300_gpio_port *port = &gpio->ports[irq - chip->base];
 	int pinoffset = port->number << 3; /* get the right stride */
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index dee7d5f06c60..97a4a3dddb30 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1396,8 +1396,8 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
 
 static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct rockchip_pin_bank *bank = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
 	u32 pend;
 
 	dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name);
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 13b45f297727..a8db57db5f5b 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1684,7 +1684,7 @@ static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
 	struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip;
 
-	chip = irq_get_chip(irq);
+	chip = irq_desc_get_chip(desc);
 	chained_irq_enter(chip, desc);
 	pcs_irq_handle(pcs_soc);
 	/* REVISIT: export and add handle_bad_irq(irq, desc)? */
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 65bf73b70e34..a4f8d38ed7be 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -1463,7 +1463,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
 static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	/* interrupt dedicated per bank */
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct st_gpio_bank *bank = gpio_chip_to_bank(gc);
 
@@ -1474,8 +1474,8 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 
 static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct st_pinctrl *info = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct st_pinctrl *info = irq_desc_get_handler_data(desc);
 	unsigned long status;
 	int n;
 
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index f3d800f796c2..7439d19af0dd 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -769,7 +769,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	const struct msm_pingroup *g;
 	struct msm_pinctrl *pctrl = to_msm_pinctrl(gc);
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int irq_pin;
 	int handled = 0;
 	u32 val;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 0b7afa50121a..66fb5ee5a8ae 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -422,9 +422,9 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
 /* interrupt handler for wakeup interrupts 0..15 */
 static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
-	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+	struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
 	struct samsung_pin_bank *bank = eintd->bank;
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int eint_irq;
 
 	chained_irq_enter(chip, desc);
@@ -454,8 +454,8 @@ static inline void exynos_irq_demux_eint(unsigned long pend,
 /* interrupt handler for wakeup interrupt 16 */
 static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
 	struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
 	unsigned long pend;
 	unsigned long mask;
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
index f1993f42114c..8d5b36e0af80 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
@@ -243,7 +243,7 @@ static struct irq_chip s3c2410_eint0_3_chip = {
 static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
+	struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
 	unsigned int virq;
 
 	/* the first 4 eints have a simple 1 to 1 mapping */
@@ -297,9 +297,9 @@ static struct irq_chip s3c2412_eint0_3_chip = {
 
 static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
 	struct irq_data *data = irq_desc_get_irq_data(desc);
-	struct s3c24xx_eint_data *eint_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	unsigned int virq;
 
 	chained_irq_enter(chip, desc);
@@ -357,11 +357,11 @@ static struct irq_chip s3c24xx_eint_chip = {
 	.irq_set_type	= s3c24xx_eint_type,
 };
 
-static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
+static inline void s3c24xx_demux_eint(struct irq_desc *desc,
 				      u32 offset, u32 range)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c24xx_eint_data *data = irq_get_handler_data(irq);
+	struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_irq_chip(desc);
 	struct samsung_pinctrl_drv_data *d = data->drvdata;
 	unsigned int pend, mask;
 
@@ -374,7 +374,7 @@ static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
 	pend &= range;
 
 	while (pend) {
-		unsigned int virq;
+		unsigned int virq, irq;
 
 		irq = __ffs(pend);
 		pend &= ~(1 << irq);
@@ -390,12 +390,12 @@ static inline void s3c24xx_demux_eint(unsigned int irq, struct irq_desc *desc,
 
 static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
 {
-	s3c24xx_demux_eint(irq, desc, 0, 0xf0);
+	s3c24xx_demux_eint(desc, 0, 0xf0);
 }
 
 static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
 {
-	s3c24xx_demux_eint(irq, desc, 8, 0xffff00);
+	s3c24xx_demux_eint(desc, 8, 0xffff00);
 }
 
 static irq_flow_handler_t s3c2410_eint_handlers[NUM_EINT_IRQ] = {
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index 7756c1e9e763..fd241d2dd165 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -410,8 +410,8 @@ static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
 
 static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
 	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
 
 	chained_irq_enter(chip, desc);
@@ -600,11 +600,10 @@ static struct irq_chip s3c64xx_eint0_irq_chip = {
 	.irq_set_type	= s3c64xx_eint0_irq_set_type,
 };
 
-static inline void s3c64xx_irq_demux_eint(unsigned int irq,
-					struct irq_desc *desc, u32 range)
+static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc);
 	struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
 	unsigned int pend, mask;
 
@@ -617,11 +616,10 @@ static inline void s3c64xx_irq_demux_eint(unsigned int irq,
 	pend &= range;
 
 	while (pend) {
-		unsigned int virq;
+		unsigned int virq, irq;
 
 		irq = fls(pend) - 1;
 		pend &= ~(1 << irq);
-
 		virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
 		/*
 		 * Something must be really wrong if an unmapped EINT
@@ -637,22 +635,22 @@ static inline void s3c64xx_irq_demux_eint(unsigned int irq,
 
 static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
 {
-	s3c64xx_irq_demux_eint(irq, desc, 0xf);
+	s3c64xx_irq_demux_eint(desc, 0xf);
 }
 
 static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
 {
-	s3c64xx_irq_demux_eint(irq, desc, 0xff0);
+	s3c64xx_irq_demux_eint(desc, 0xff0);
 }
 
 static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
 {
-	s3c64xx_irq_demux_eint(irq, desc, 0xff000);
+	s3c64xx_irq_demux_eint(desc, 0xff000);
 }
 
 static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
 {
-	s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
+	s3c64xx_irq_demux_eint(desc, 0xff00000);
 }
 
 static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index e2efbbae4061..46cafde08ebf 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -552,7 +552,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
 	struct sirfsoc_gpio_bank *bank;
 	u32 status, ctrl;
 	int idx = 0;
-	struct irq_chip *chip = irq_get_chip(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int i;
 
 	for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index f8e171b76693..563cec6dc24e 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -711,8 +711,8 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
 
 static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct irq_chip *chip = irq_get_chip(irq);
-	struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct sunxi_pinctrl *pctl = irq_desc_get_handler_data(desc);
 	unsigned long bank, reg, val;
 
 	for (bank = 0; bank < pctl->desc->irq_banks; bank++)
-- 
1.7.10.4



From jiang.liu at linux.intel.com  Wed Jun  3 21:13:54 2015
From: jiang.liu at linux.intel.com (Jiang Liu)
Date: Thu,  4 Jun 2015 12:13:54 +0800
Subject: [RFT v2 44/48] genirq,
 pinctrl: Kill the first parameter 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>

Now most IRQ flow handlers make no use of the first parameter 'irq'.
And for those who do make use of 'irq', we could easily get the irq
number through irq_desc->irq_data->irq. So kill the first parameter
'irq' of irq_flow_handler_t.

To ease review, I have split the changes into several parts, though
they should be merge as one to support bisecting.

Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
---
 drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c     |    2 +-
 drivers/pinctrl/intel/pinctrl-baytrail.c      |    2 +-
 drivers/pinctrl/intel/pinctrl-cherryview.c    |    2 +-
 drivers/pinctrl/intel/pinctrl-intel.c         |    2 +-
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    2 +-
 drivers/pinctrl/nomadik/pinctrl-nomadik.c     |    4 ++--
 drivers/pinctrl/pinctrl-adi2.c                |    3 +--
 drivers/pinctrl/pinctrl-amd.c                 |    4 ++--
 drivers/pinctrl/pinctrl-at91.c                |    2 +-
 drivers/pinctrl/pinctrl-coh901.c              |    2 +-
 drivers/pinctrl/pinctrl-rockchip.c            |    2 +-
 drivers/pinctrl/pinctrl-single.c              |    2 +-
 drivers/pinctrl/pinctrl-st.c                  |    4 ++--
 drivers/pinctrl/qcom/pinctrl-msm.c            |    4 ++--
 drivers/pinctrl/samsung/pinctrl-exynos.c      |    4 ++--
 drivers/pinctrl/samsung/pinctrl-s3c24xx.c     |    8 ++++----
 drivers/pinctrl/samsung/pinctrl-s3c64xx.c     |   10 +++++-----
 drivers/pinctrl/sirf/pinctrl-sirf.c           |    4 ++--
 drivers/pinctrl/spear/pinctrl-plgpio.c        |    2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         |    2 +-
 20 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
index 4ad5c1a996e3..df940687524f 100644
--- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
@@ -143,7 +143,7 @@ static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
 	return !!(readl(chip->base + offset) & BIT(shift));
 }
 
-static void cygnus_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void cygnus_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 2062c224e32f..94870cedb0ad 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -421,7 +421,7 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	spin_unlock_irqrestore(&vg->lock, flags);
 }
 
-static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void byt_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
 	struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 878e798bcb56..cfdc5f1c9cd6 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1364,7 +1364,7 @@ static struct irq_chip chv_gpio_irqchip = {
 	.flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
-static void chv_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void chv_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct chv_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index a40681097402..a64ca4bd69cd 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -836,7 +836,7 @@ static void intel_gpio_community_irq_handler(struct gpio_chip *gc,
 	}
 }
 
-static void intel_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void intel_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct intel_pinctrl *pctrl = gpiochip_to_pinctrl(gc);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index fd05ca6125b0..9ec45d4875db 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1016,7 +1016,7 @@ mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
 	}
 }
 
-static void mtk_eint_irq_handler(unsigned irq, struct irq_desc *desc)
+static void mtk_eint_irq_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index 902f53b855bf..cd70a30f8d8e 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -871,7 +871,7 @@ static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status)
 	chained_irq_exit(host_chip, desc);
 }
 
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void nmk_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
@@ -884,7 +884,7 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	__nmk_gpio_irq_handler(desc, status);
 }
 
-static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void nmk_gpio_latent_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip);
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 8434439c5017..6a004582cee4 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -530,8 +530,7 @@ static inline void preflow_handler(struct irq_desc *desc)
 static inline void preflow_handler(struct irq_desc *desc) { }
 #endif
 
-static void adi_gpio_handle_pint_irq(unsigned int inta_irq,
-			struct irq_desc *desc)
+static void adi_gpio_handle_pint_irq(struct irq_desc *desc)
 {
 	u32 request;
 	u32 level_mask, hwirq;
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 31e206613814..0227fd66a555 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -492,7 +492,7 @@ static struct irq_chip amd_gpio_irqchip = {
 	.irq_set_type = amd_gpio_irq_set_type,
 };
 
-static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
+static void amd_gpio_irq_handler(struct irq_desc *desc)
 {
 	u32 i;
 	u32 off;
@@ -542,7 +542,7 @@ static void amd_gpio_irq_handler(unsigned int __irq, struct irq_desc *desc)
 	}
 
 	if (handled == 0)
-		handle_bad_irq(__irq, desc);
+		handle_bad_irq(desc);
 
 	spin_lock_irqsave(&gpio_dev->lock, flags);
 	reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 92d5f9ec1cce..0145257991fe 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1579,7 +1579,7 @@ static struct irq_chip gpio_irqchip = {
 	.irq_set_wake	= gpio_irq_set_wake,
 };
 
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void gpio_irq_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct gpio_chip *gpio_chip = irq_desc_get_handler_data(desc);
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 3731cc67a88b..9c9b88934bcc 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -519,7 +519,7 @@ static struct irq_chip u300_gpio_irqchip = {
 	.irq_set_type		= u300_gpio_irq_type,
 };
 
-static void u300_gpio_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void u300_gpio_irq_handler(struct irq_desc *desc)
 {
 	unsigned int irq = irq_desc_get_irq(desc);
 	struct irq_chip *parent_chip = irq_desc_get_chip(desc);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 1fff71221d83..c2cc5d3e81d5 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1394,7 +1394,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
  * Interrupt handling
  */
 
-static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc)
+static void rockchip_irq_demux(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc);
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index a8db57db5f5b..d71cad948bf2 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1679,7 +1679,7 @@ static irqreturn_t pcs_irq_handler(int irq, void *d)
  * Use this if you have a separate interrupt for each
  * pinctrl-single instance.
  */
-static void pcs_irq_chain_handler(unsigned int irq, struct irq_desc *desc)
+static void pcs_irq_chain_handler(struct irq_desc *desc)
 {
 	struct pcs_soc_data *pcs_soc = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip;
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index a4f8d38ed7be..8f92e929582d 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -1460,7 +1460,7 @@ static void __gpio_irq_handler(struct st_gpio_bank *bank)
 	}
 }
 
-static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void st_gpio_irq_handler(struct irq_desc *desc)
 {
 	/* interrupt dedicated per bank */
 	struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -1472,7 +1472,7 @@ static void st_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 	chained_irq_exit(chip, desc);
 }
 
-static void st_gpio_irqmux_handler(unsigned irq, struct irq_desc *desc)
+static void st_gpio_irqmux_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct st_pinctrl *info = irq_desc_get_handler_data(desc);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 7439d19af0dd..1d2e642130ab 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -764,7 +764,7 @@ static struct irq_chip msm_gpio_irq_chip = {
 	.irq_set_wake   = msm_gpio_irq_set_wake,
 };
 
-static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void msm_gpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	const struct msm_pingroup *g;
@@ -793,7 +793,7 @@ static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 	/* No interrupts were flagged */
 	if (handled == 0)
-		handle_bad_irq(irq, desc);
+		handle_bad_irq(desc);
 
 	chained_irq_exit(chip, desc);
 }
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 66fb5ee5a8ae..5a5eba7c697d 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -420,7 +420,7 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
 };
 
 /* interrupt handler for wakeup interrupts 0..15 */
-static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_eint0_15(struct irq_desc *desc)
 {
 	struct exynos_weint_data *eintd = irq_desc_get_handler_data(desc);
 	struct samsung_pin_bank *bank = eintd->bank;
@@ -452,7 +452,7 @@ static inline void exynos_irq_demux_eint(unsigned long pend,
 }
 
 /* interrupt handler for wakeup interrupt 16 */
-static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
index 8d5b36e0af80..3d2e0f9cd52a 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
@@ -240,7 +240,7 @@ static struct irq_chip s3c2410_eint0_3_chip = {
 	.irq_set_type	= s3c24xx_eint_type,
 };
 
-static void s3c2410_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c2410_demux_eint0_3(struct irq_desc *desc)
 {
 	struct irq_data *data = irq_desc_get_irq_data(desc);
 	struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
@@ -295,7 +295,7 @@ static struct irq_chip s3c2412_eint0_3_chip = {
 	.irq_set_type	= s3c24xx_eint_type,
 };
 
-static void s3c2412_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c2412_demux_eint0_3(struct irq_desc *desc)
 {
 	struct s3c24xx_eint_data *eint_data = irq_desc_get_handler_data(desc);
 	struct irq_data *data = irq_desc_get_irq_data(desc);
@@ -388,12 +388,12 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc,
 	chained_irq_exit(chip, desc);
 }
 
-static void s3c24xx_demux_eint4_7(unsigned int irq, struct irq_desc *desc)
+static void s3c24xx_demux_eint4_7(struct irq_desc *desc)
 {
 	s3c24xx_demux_eint(desc, 0, 0xf0);
 }
 
-static void s3c24xx_demux_eint8_23(unsigned int irq, struct irq_desc *desc)
+static void s3c24xx_demux_eint8_23(struct irq_desc *desc)
 {
 	s3c24xx_demux_eint(desc, 8, 0xffff00);
 }
diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
index fd241d2dd165..5c5beb5bdd6c 100644
--- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -408,7 +408,7 @@ static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
 	.xlate	= irq_domain_xlate_twocell,
 };
 
-static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_eint_gpio_irq(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc);
@@ -633,22 +633,22 @@ static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range)
 	chained_irq_exit(chip, desc);
 }
 
-static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint0_3(struct irq_desc *desc)
 {
 	s3c64xx_irq_demux_eint(desc, 0xf);
 }
 
-static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint4_11(struct irq_desc *desc)
 {
 	s3c64xx_irq_demux_eint(desc, 0xff0);
 }
 
-static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint12_19(struct irq_desc *desc)
 {
 	s3c64xx_irq_demux_eint(desc, 0xff000);
 }
 
-static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+static void s3c64xx_demux_eint20_27(struct irq_desc *desc)
 {
 	s3c64xx_irq_demux_eint(desc, 0xff00000);
 }
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 89792e12d744..d3659688f440 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -545,7 +545,7 @@ static struct irq_chip sirfsoc_irq_chip = {
 	.irq_set_type = sirfsoc_gpio_irq_type,
 };
 
-static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
+static void sirfsoc_gpio_handle_irq(struct irq_desc *desc)
 {
 	unsigned int irq = irq_desc_get_irq(desc);
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
@@ -570,7 +570,7 @@ static void sirfsoc_gpio_handle_irq(unsigned int __irq, struct irq_desc *desc)
 		printk(KERN_WARNING
 			"%s: gpio id %d status %#x no interrupt is flagged\n",
 			__func__, bank->id, status);
-		handle_bad_irq(irq, desc);
+		handle_bad_irq(desc);
 		return;
 	}
 
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index ae8f29fb5536..1f0af250dbb5 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -356,7 +356,7 @@ static struct irq_chip plgpio_irqchip = {
 	.irq_set_type	= plgpio_irq_set_type,
 };
 
-static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+static void plgpio_irq_handler(struct irq_desc *desc)
 {
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
 	struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ace032681d82..12c78f7330d2 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -709,7 +709,7 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
 			  IRQCHIP_EOI_IF_HANDLED,
 };
 
-static void sunxi_pinctrl_irq_handler(unsigned __irq, struct irq_desc *desc)
+static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
 {
 	unsigned int irq = irq_desc_get_irq(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-- 
1.7.10.4



From paul at pwsan.com  Thu Jun  4 16:02:25 2015
From: paul at pwsan.com (Paul Walmsley)
Date: Thu, 4 Jun 2015 23:02:25 +0000 (UTC)
Subject: [PATCH v2 1/2] clk: change clk_ops' ->round_rate() prototype
In-Reply-To: <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
References: <1430407809-31147-1-git-send-email-boris.brezillon@free-electrons.com>
 <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
Message-ID: <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>

Hi folks

just a brief comment on this one:

On Thu, 30 Apr 2015, Boris Brezillon wrote:

> Clock rates are stored in an unsigned long field, but ->round_rate()
> (which returns a rounded rate from a requested one) returns a long
> value (errors are reported using negative error codes), which can lead
> to long overflow if the clock rate exceed 2Ghz.
> 
> Change ->round_rate() prototype to return 0 or an error code, and pass the
> requested rate as a pointer so that it can be adjusted depending on
> hardware capabilities.

...

> diff --git a/Documentation/clk.txt b/Documentation/clk.txt
> index 0e4f90a..fca8b7a 100644
> --- a/Documentation/clk.txt
> +++ b/Documentation/clk.txt
> @@ -68,8 +68,8 @@ the operations defined in clk.h:
>  		int		(*is_enabled)(struct clk_hw *hw);
>  		unsigned long	(*recalc_rate)(struct clk_hw *hw,
>  						unsigned long parent_rate);
> -		long		(*round_rate)(struct clk_hw *hw,
> -						unsigned long rate,
> +		int		(*round_rate)(struct clk_hw *hw,
> +						unsigned long *rate,
>  						unsigned long *parent_rate);
>  		long		(*determine_rate)(struct clk_hw *hw,
>  						unsigned long rate,

I'd suggest that we should probably go straight to 64-bit rates.  There 
are already plenty of clock sources that can generate rates higher than 
4GiHz.


- Paul


From tomasz.figa at gmail.com  Thu Jun  4 20:06:06 2015
From: tomasz.figa at gmail.com (Tomasz Figa)
Date: Fri, 5 Jun 2015 12:06:06 +0900
Subject: [RFT v2 06/48] pinctrl: Use irq_desc_get_xxx() to avoid redundant
 lookup of irq_desc
In-Reply-To: <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CA+Ln22Euot24co7qKLTej43j3Z2BS-p5WhjRq9WgRb-+U=Tyqw@mail.gmail.com>

Hi,

2015-06-04 13:13 GMT+09:00 Jiang Liu <jiang.liu at linux.intel.com>:
> Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc while we
> already have a pointer to corresponding irq_desc.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  drivers/pinctrl/intel/pinctrl-cherryview.c    |    2 +-
>  drivers/pinctrl/intel/pinctrl-intel.c         |    2 +-
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    4 ++--
>  drivers/pinctrl/nomadik/pinctrl-nomadik.c     |   12 +++++-------
>  drivers/pinctrl/pinctrl-amd.c                 |    2 +-
>  drivers/pinctrl/pinctrl-at91.c                |    2 +-
>  drivers/pinctrl/pinctrl-coh901.c              |    4 ++--
>  drivers/pinctrl/pinctrl-rockchip.c            |    4 ++--
>  drivers/pinctrl/pinctrl-single.c              |    2 +-
>  drivers/pinctrl/pinctrl-st.c                  |    6 +++---
>  drivers/pinctrl/qcom/pinctrl-msm.c            |    2 +-
>  drivers/pinctrl/samsung/pinctrl-exynos.c      |    8 ++++----
>  drivers/pinctrl/samsung/pinctrl-s3c24xx.c     |   18 +++++++++---------
>  drivers/pinctrl/samsung/pinctrl-s3c64xx.c     |   22 ++++++++++------------

For Samsung stuff:

Acked-by: Tomasz Figa <tomasz.figa at gmail.com>

Best regards,
Tomasz


From tomasz.figa at gmail.com  Thu Jun  4 20:08:06 2015
From: tomasz.figa at gmail.com (Tomasz Figa)
Date: Fri, 5 Jun 2015 12:08:06 +0900
Subject: [RFT v2 44/48] genirq,
 pinctrl: Kill the first parameter 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CA+Ln22EHa-Bnybf2bd2-U1QvNOBThjpjj_uuz95aBAzniN2f1Q@mail.gmail.com>

Hi,

2015-06-04 13:13 GMT+09:00 Jiang Liu <jiang.liu at linux.intel.com>:
> Now most IRQ flow handlers make no use of the first parameter 'irq'.
> And for those who do make use of 'irq', we could easily get the irq
> number through irq_desc->irq_data->irq. So kill the first parameter
> 'irq' of irq_flow_handler_t.
>
> To ease review, I have split the changes into several parts, though
> they should be merge as one to support bisecting.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> ---
>  drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c     |    2 +-
>  drivers/pinctrl/intel/pinctrl-baytrail.c      |    2 +-
>  drivers/pinctrl/intel/pinctrl-cherryview.c    |    2 +-
>  drivers/pinctrl/intel/pinctrl-intel.c         |    2 +-
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    2 +-
>  drivers/pinctrl/nomadik/pinctrl-nomadik.c     |    4 ++--
>  drivers/pinctrl/pinctrl-adi2.c                |    3 +--
>  drivers/pinctrl/pinctrl-amd.c                 |    4 ++--
>  drivers/pinctrl/pinctrl-at91.c                |    2 +-
>  drivers/pinctrl/pinctrl-coh901.c              |    2 +-
>  drivers/pinctrl/pinctrl-rockchip.c            |    2 +-
>  drivers/pinctrl/pinctrl-single.c              |    2 +-
>  drivers/pinctrl/pinctrl-st.c                  |    4 ++--
>  drivers/pinctrl/qcom/pinctrl-msm.c            |    4 ++--
>  drivers/pinctrl/samsung/pinctrl-exynos.c      |    4 ++--
>  drivers/pinctrl/samsung/pinctrl-s3c24xx.c     |    8 ++++----
>  drivers/pinctrl/samsung/pinctrl-s3c64xx.c     |   10 +++++-----

Assuming that it was properly compile tested, for Samsung stuff:

Acked-by: Tomasz Figa <tomasz.figa at gmail.com>

Best regards,
Tomasz


From wxt at rock-chips.com  Fri Jun  5 02:00:02 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri, 05 Jun 2015 17:00:02 +0800
Subject: [PATCH 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1604172.FydsUUUXNY@diego>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
 <1433479677-18086-2-git-send-email-wxt@rock-chips.com>
 <1604172.FydsUUUXNY@diego>
Message-ID: <55716512.9050603@rock-chips.com>

Heiko,

? 2015?06?05? 16:45, Heiko St?bner ??:
> Hi Caesar,
>
>
> thanks for investigating this.
>
> Am Freitag, 5. Juni 2015, 12:47:55 schrieb Caesar Wang:
>> In general, the correct flow is:
>>
>> cpu off:
>>      reset_control_assert
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>>
>> cpu on:
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>>      reset_control_deassert
>>
>> You can repro it with bringing CPU up and down.
>> Says:(test scripts)
>>
>>      cd /sys/devices/system/cpu/
>>      for i in $(seq 1000); do
>>      echo "================= $i ============"
>>          for j in $(seq 100); do
>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
>> cpu3/online)" != "000" ]]; do echo 0 > cpu1/online
>>                  echo 0 > cpu2/online
>>                  echo 0 > cpu3/online
>>              done
>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
>> cpu3/online)" != "111" ]]; do echo 1 > cpu1/online
>>                  echo 1 > cpu2/online
>>                  echo 1 > cpu3/online
>>              done
>>          done
>>      done
>>
>> The following is reproducile log:
>> [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>> [34466.186824] Disabling non-boot CPUs ...
>> [34466.187509] CPU1: shutdown
>> [34466.188672] CPU2: shutdown
>> [34473.736627] Kernel panic - not syncing: Watchdog detected hard LOCKUP on
>> cpu 0 [34473.736646] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 3.14.0 #1
>> [34473.736687] [<c010dfb0>] (unwind_backtrace) from [<c010a460>]
>> (show_stack+0x20/0x24) [34473.736711] [<c010a460>] (show_stack) from
>> [<c0630670>] (dump_stack+0x70/0x8c) [34473.736731] [<c0630670>]
>> (dump_stack) from [<c062fa0c>] (panic+0xa8/0x1fc) [34473.736754]
>> [<c062fa0c>] (panic) from [<c0191efc>] (watchdog_timer_fn+0x234/0x26c)
>> [34473.736777] [<c0191efc>] (watchdog_timer_fn) from [<c014103c>]
>> (__run_hrtimer+0x118/0x1e0) [34473.736797] [<c014103c>] (__run_hrtimer)
>> from [<c0141c04>] (hrtimer_interrupt+0x148/0x2a0) [34473.736820]
>> [<c0141c04>] (hrtimer_interrupt) from [<c04d9994>]
>> (arch_timer_handler_phys+0x38/0x48) [34473.736844] [<c04d9994>]
>> (arch_timer_handler_phys) from [<c016acc4>]
>> (handle_percpu_devid_irq+0xb8/0x124) [34473.736867] [<c016acc4>]
>> (handle_percpu_devid_irq) from [<c0166a30>] (generic_handle_irq+0x30/0x40)
>> [34473.736887] [<c0166a30>] (generic_handle_irq) from [<c0166d28>]
>> (__handle_domain_irq+0x8c/0xb0) [34473.736905] [<c0166d28>]
>> (__handle_domain_irq) from [<c01003a0>] (gic_handle_irq+0x48/0x6c)
>> [34473.736922] [<c01003a0>] (gic_handle_irq) from [<c010b040>]
>> (__irq_svc+0x40/0x50) [34473.736936] Exception stack(0xee127f70 to
>> 0xee127fb8)
>> [34473.736948] 7f60:                                     ffffffed 00000000
>> 2dd6d000 00000000 [34473.736964] 7f80: ee126000 00000015 c0b46bac c0b46bac
>> 0000406a 410fc0d1 00000000 ee127fc4 [34473.736979] 7fa0: ee127fb8 ee127fb8
>> c0107038 c010703c 600f0013 ffffffff [34473.736995] [<c010b040>] (__irq_svc)
>> from [<c010703c>] (arch_cpu_idle+0x40/0x48) [34473.737013] [<c010703c>]
>> (arch_cpu_idle) from [<c0166978>] (cpu_startup_entry+0x170/0x1d0)
>> [34473.737031] [<c0166978>] (cpu_startup_entry) from [<c010c254>]
>> (secondary_start_kernel+0x138/0x160) [34473.737059] [<c010c254>]
>> (secondary_start_kernel) from [<00100464>] (0x100464) [34474.903740] SMP:
>> failed to stop secondary CPUs
>> [34476.099964] SMP: failed to stop secondary CPUs
>> ...
>>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> ---
>>
>>   arch/arm/mach-rockchip/platsmp.c | 13 +++++--------
>>   1 file changed, 5 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm/mach-rockchip/platsmp.c
>> b/arch/arm/mach-rockchip/platsmp.c index 5b4ca3c..1230d3d 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -88,20 +88,17 @@ static int pmu_set_power_domain(int pd, bool on)
>>   			return PTR_ERR(rstc);
>>   		}
>>
>> -		if (on)
>> +		if (on) {
>> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>>   			reset_control_deassert(rstc);
>> -		else
>> +		} else {
>>   			reset_control_assert(rstc);
>> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>> +		}
> you're loosing the return value of regmap_update_bits here, I guess it should
> look like below?
>
> 		if (on) {
> 			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);

I search the kernel, Nobody do that return value.
Need we are that?
I will fix it on next patch if it's need.
> 			if (ret < 0) {
> 				pr_err("%s: could not update power domain\n", __func__);
> 		  		reset_control_put(rstc);
> 				return ret;
> 			}
>
> 			reset_control_deassert(rstc);
> 		} else {
> 			reset_control_assert(rstc);
>
> 			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> 			if (ret < 0) {
> 				pr_err("%s: could not update power domain\n", __func__);
> 		  		reset_control_put(rstc);
> 				return ret;
> 			}
> 		}
>
>
>>   		reset_control_put(rstc);
>>   	}
>>
>> -	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>> -	if (ret < 0) {
>> -		pr_err("%s: could not update power domain\n", __func__);
>> -		return ret;
>> -	}
>> -
>>   	ret = -1;
>>   	while (ret != on) {
>>   		ret = pmu_power_domain_is_on(pd);
> second question - with this patch, what happens actually is
>
>   cpu off:
>       reset_control_assert
>       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>       wait_for_power_domain_to_turn_off
>   
>   cpu on:
>       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>       reset_control_deassert
>       wait_for_power_domain_to_turn_on
>
> So shouldn't the deassertion of the reset happen after the powerdomain
> sucessfull turned on? Like
>
>   cpu on:
>       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>       wait_for_power_domain_to_turn_on
>       reset_control_deassert

You are right.
>
>
>

-- 
Thanks,
- Caesar




From heiko at sntech.de  Fri Jun  5 02:46:21 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 11:46:21 +0200
Subject: [PATCH 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <55716512.9050603@rock-chips.com>
References: <1433479677-18086-1-git-send-email-wxt@rock-chips.com>
 <1604172.FydsUUUXNY@diego> <55716512.9050603@rock-chips.com>
Message-ID: <26548754.3lOPTtJQ55@diego>

Am Freitag, 5. Juni 2015, 17:00:02 schrieb Caesar Wang:
> Heiko,
> 
> ? 2015?06?05? 16:45, Heiko St?bner ??:
> > Hi Caesar,
> > 
> > 
> > thanks for investigating this.
> > 
> > Am Freitag, 5. Juni 2015, 12:47:55 schrieb Caesar Wang:
> >> In general, the correct flow is:
> >> 
> >> cpu off:
> >>      reset_control_assert
> >>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
> >> 
> >> cpu on:
> >>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
> >>      reset_control_deassert
> >> 
> >> You can repro it with bringing CPU up and down.
> >> Says:(test scripts)
> >> 
> >>      cd /sys/devices/system/cpu/
> >>      for i in $(seq 1000); do
> >>      echo "================= $i ============"
> >>      
> >>          for j in $(seq 100); do
> >>          
> >>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> >> 
> >> cpu3/online)" != "000" ]]; do echo 0 > cpu1/online
> >> 
> >>                  echo 0 > cpu2/online
> >>                  echo 0 > cpu3/online
> >>              
> >>              done
> >>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> >> 
> >> cpu3/online)" != "111" ]]; do echo 1 > cpu1/online
> >> 
> >>                  echo 1 > cpu2/online
> >>                  echo 1 > cpu3/online
> >>              
> >>              done
> >>          
> >>          done
> >>      
> >>      done
> >> 
> >> The following is reproducile log:
> >> [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
> >> [34466.186824] Disabling non-boot CPUs ...
> >> [34466.187509] CPU1: shutdown
> >> [34466.188672] CPU2: shutdown
> >> [34473.736627] Kernel panic - not syncing: Watchdog detected hard LOCKUP
> >> on
> >> cpu 0 [34473.736646] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 3.14.0 #1
> >> [34473.736687] [<c010dfb0>] (unwind_backtrace) from [<c010a460>]
> >> (show_stack+0x20/0x24) [34473.736711] [<c010a460>] (show_stack) from
> >> [<c0630670>] (dump_stack+0x70/0x8c) [34473.736731] [<c0630670>]
> >> (dump_stack) from [<c062fa0c>] (panic+0xa8/0x1fc) [34473.736754]
> >> [<c062fa0c>] (panic) from [<c0191efc>] (watchdog_timer_fn+0x234/0x26c)
> >> [34473.736777] [<c0191efc>] (watchdog_timer_fn) from [<c014103c>]
> >> (__run_hrtimer+0x118/0x1e0) [34473.736797] [<c014103c>] (__run_hrtimer)
> >> from [<c0141c04>] (hrtimer_interrupt+0x148/0x2a0) [34473.736820]
> >> [<c0141c04>] (hrtimer_interrupt) from [<c04d9994>]
> >> (arch_timer_handler_phys+0x38/0x48) [34473.736844] [<c04d9994>]
> >> (arch_timer_handler_phys) from [<c016acc4>]
> >> (handle_percpu_devid_irq+0xb8/0x124) [34473.736867] [<c016acc4>]
> >> (handle_percpu_devid_irq) from [<c0166a30>]
> >> (generic_handle_irq+0x30/0x40)
> >> [34473.736887] [<c0166a30>] (generic_handle_irq) from [<c0166d28>]
> >> (__handle_domain_irq+0x8c/0xb0) [34473.736905] [<c0166d28>]
> >> (__handle_domain_irq) from [<c01003a0>] (gic_handle_irq+0x48/0x6c)
> >> [34473.736922] [<c01003a0>] (gic_handle_irq) from [<c010b040>]
> >> (__irq_svc+0x40/0x50) [34473.736936] Exception stack(0xee127f70 to
> >> 0xee127fb8)
> >> [34473.736948] 7f60:                                     ffffffed
> >> 00000000
> >> 2dd6d000 00000000 [34473.736964] 7f80: ee126000 00000015 c0b46bac
> >> c0b46bac
> >> 0000406a 410fc0d1 00000000 ee127fc4 [34473.736979] 7fa0: ee127fb8
> >> ee127fb8
> >> c0107038 c010703c 600f0013 ffffffff [34473.736995] [<c010b040>]
> >> (__irq_svc)
> >> from [<c010703c>] (arch_cpu_idle+0x40/0x48) [34473.737013] [<c010703c>]
> >> (arch_cpu_idle) from [<c0166978>] (cpu_startup_entry+0x170/0x1d0)
> >> [34473.737031] [<c0166978>] (cpu_startup_entry) from [<c010c254>]
> >> (secondary_start_kernel+0x138/0x160) [34473.737059] [<c010c254>]
> >> (secondary_start_kernel) from [<00100464>] (0x100464) [34474.903740] SMP:
> >> failed to stop secondary CPUs
> >> [34476.099964] SMP: failed to stop secondary CPUs
> >> ...
> >> 
> >> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> >> ---
> >> 
> >>   arch/arm/mach-rockchip/platsmp.c | 13 +++++--------
> >>   1 file changed, 5 insertions(+), 8 deletions(-)
> >> 
> >> diff --git a/arch/arm/mach-rockchip/platsmp.c
> >> b/arch/arm/mach-rockchip/platsmp.c index 5b4ca3c..1230d3d 100644
> >> --- a/arch/arm/mach-rockchip/platsmp.c
> >> +++ b/arch/arm/mach-rockchip/platsmp.c
> >> @@ -88,20 +88,17 @@ static int pmu_set_power_domain(int pd, bool on)
> >> 
> >>   			return PTR_ERR(rstc);
> >>   		
> >>   		}
> >> 
> >> -		if (on)
> >> +		if (on) {
> >> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> >> 
> >>   			reset_control_deassert(rstc);
> >> 
> >> -		else
> >> +		} else {
> >> 
> >>   			reset_control_assert(rstc);
> >> 
> >> +			regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> >> +		}
> > 
> > you're loosing the return value of regmap_update_bits here, I guess it
> > should look like below?
> > 
> > 		if (on) {
> > 		
> > 			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> 
> I search the kernel, Nobody do that return value.

counter-example:
http://lxr.free-electrons.com/source/drivers/phy/phy-exynos5250-sata.c#L76
;-)

> Need we are that?
> I will fix it on next patch if it's need.

yes, while not very probable, it is nevertheless still good practice to handle 
it. But when chaning the logic as we observed below, the regmap update part 
can already stay how it is now, as you can simply do something like:

if (!on)
	reset_control_assert(rstc);

regmap_update_bits
wait_for_pd

if (on)
	reset_control_deassert(rstc);


Heiko

> > 			if (ret < 0) {
> > 			
> > 				pr_err("%s: could not update power domain\n", __func__);
> > 				
> > 		  		reset_control_put(rstc);
> > 				
> > 				return ret;
> > 			
> > 			}
> > 			
> > 			reset_control_deassert(rstc);
> > 		
> > 		} else {
> > 		
> > 			reset_control_assert(rstc);
> > 			
> > 			ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> > 			if (ret < 0) {
> > 			
> > 				pr_err("%s: could not update power domain\n", __func__);
> > 				
> > 		  		reset_control_put(rstc);
> > 				
> > 				return ret;
> > 			
> > 			}
> > 		
> > 		}
> > 		
> >>   		reset_control_put(rstc);
> >>   	
> >>   	}
> >> 
> >> -	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> >> -	if (ret < 0) {
> >> -		pr_err("%s: could not update power domain\n", __func__);
> >> -		return ret;
> >> -	}
> >> -
> >> 
> >>   	ret = -1;
> >>   	while (ret != on) {
> >>   	
> >>   		ret = pmu_power_domain_is_on(pd);
> > 
> > second question - with this patch, what happens actually is
> > 
> >   cpu off:
> >       reset_control_assert
> >       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
> >       wait_for_power_domain_to_turn_off
> >   
> >   cpu on:
> >       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
> >       reset_control_deassert
> >       wait_for_power_domain_to_turn_on
> > 
> > So shouldn't the deassertion of the reset happen after the powerdomain
> > sucessfull turned on? Like
> > 
> >   cpu on:
> >       regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
> >       wait_for_power_domain_to_turn_on
> >       reset_control_deassert
> 
> You are right.



From thierry.reding at gmail.com  Fri Jun  5 04:02:01 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri, 5 Jun 2015 13:02:01 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <2619686.csNBBFyt8W@phil>
References: <4184159.j0iXe39dFB@phil>
 <2619686.csNBBFyt8W@phil>
Message-ID: <20150605110159.GA16254@ulmo.nvidia.com>

On Mon, Mar 23, 2015 at 07:17:49PM +0100, Heiko Stuebner wrote:
> Hi Philipp,
> 
> Am Donnerstag, 12. M?rz 2015, 21:45:19 schrieb Heiko Stuebner:
> > At least the Rockchip variant of the dw_hdmi can have controllable power
> > supplies providing 1.0 and 1.8V. Therefore add the possibility for the
> > generic bridge driver to enable supplies provided by the hw-specific
> > drivers.
> > 
> > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> 
> does this look ok now?
> 
> And as we talked about in Chemnitz, who will be taking such bridge-related 
> changes, as you mentioned some last bridge-patches going through Thierry.

Sorry, I had completely missed this.

> > ---
> > changes since v2:
> > - rename supplies to the names found in the hdmi IP databook
> > changes since v1:
> > - follow suggestion from Russell King to keep regulator handling local
> >   to the rockchip implementation for the time being and only generalize
> >   when a real second implementation needs regulator handling
> > 
> >  .../devicetree/bindings/drm/bridge/dw_hdmi.txt     |  5 ++++
> >  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        | 32
> > +++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt index
> > a905c14..bb74640 100644
> > --- a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > +++ b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > @@ -22,6 +22,11 @@ Optional properties
> >  - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
> >  - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
> > 
> > +Optional supplies:
> > +rockchip,rk3288-dw-hdmi handles two optional power supplies:
> > +- vp-supply: 1.0V power supply
> > +- vph-supply: 1.8V power supply

If this is specific to the Rockchip implementation, shouldn't this go
into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
could then simply go into the Rockchip DRM tree.

Thierry


From wxt at rock-chips.com  Fri Jun  5 04:39:19 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 19:39:19 +0800
Subject: [PATCH v2 0/3]     ARM: rockchip: fix the SMP
Message-ID: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>

    Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 56 +++++++++++++++++++++++++++-------------
 1 file changed, 38 insertions(+), 18 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 04:39:21 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 19:39:21 +0800
Subject: [PATCH v2 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
References: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433504362-7549-3-git-send-email-wxt@rock-chips.com>

In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
WFI/WFE state.
we can delay 1ms to ensure the CPU enter WFI/WFE state.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 1d4659e..17b3473 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -335,6 +335,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 04:39:20 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 19:39:20 +0800
Subject: [PATCH v2 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
References: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433504362-7549-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert

This is needed for stressing CPU up/down, as per:

    cd /sys/devices/system/cpu/
    for i in $(seq 1000); do
      echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000" ]]; do
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669
    msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing: Watchdog detected hard
    LOCKUP on cpu 0
    .......

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 46 +++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..1d4659e 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -88,28 +88,44 @@ static int pmu_set_power_domain(int pd, bool on)
 			return PTR_ERR(rstc);
 		}
 
-		if (on)
-			reset_control_deassert(rstc);
-		else
+		if (!on)
 			reset_control_assert(rstc);
 
-		reset_control_put(rstc);
-	}
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			reset_control_put(rstc);
+			return ret;
+		}
 
-	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
-	if (ret < 0) {
-		pr_err("%s: could not update power domain\n", __func__);
-		return ret;
-	}
+		ret = -1;
+		while (ret != on) {
+			ret = pmu_power_domain_is_on(pd);
+			if (ret < 0) {
+				pr_err("%s: could not read power domain state\n",
+				       __func__);
+				return ret;
+			}
+		}
 
-	ret = -1;
-	while (ret != on) {
-		ret = pmu_power_domain_is_on(pd);
+		if (on)
+			reset_control_deassert(rstc);
+	} else {
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
 		if (ret < 0) {
-			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			pr_err("%s: could not update power domain\n", __func__);
 			return ret;
 		}
+
+		ret = -1;
+		while (ret != on) {
+			ret = pmu_power_domain_is_on(pd);
+			if (ret < 0) {
+				pr_err("%s: could not read power domain state\n",
+				       __func__);
+				return ret;
+			}
+		}
 	}
 
 	return 0;
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 04:39:22 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 19:39:22 +0800
Subject: [PATCH v2 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
References: <1433504362-7549-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433504362-7549-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
Although there is a check, it's no matter.

CHECK: usleep_range is preferred over udelay; see
Documentation/timers/timers-howto.txt
+167udelay(10);
total: 0 errors, 0 warnings, 1 checks, 362 lines checked

 Changes in v2:
    - As Kever points out, Fix the subject typo WIF/WFI in PATCH [2/3].
    - As Heiko suggestion, re-adjust the cpu on/off flow in PATCH [1/3].
    - Use the checkpatch.pl -f --subjective to check in PATCH [3/3].

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 17b3473..fc50e1f 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -147,7 +147,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -166,7 +166,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		udelay(10);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -345,7 +345,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -358,4 +358,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From heiko at sntech.de  Fri Jun  5 05:16:40 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 14:16:40 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150605110159.GA16254@ulmo.nvidia.com>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
Message-ID: <23123577.mOoqGCAPdL@diego>

Hi Thierry

Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> On Mon, Mar 23, 2015 at 07:17:49PM +0100, Heiko Stuebner wrote:
> > Hi Philipp,
> > 
> > Am Donnerstag, 12. M?rz 2015, 21:45:19 schrieb Heiko Stuebner:
> > > At least the Rockchip variant of the dw_hdmi can have controllable power
> > > supplies providing 1.0 and 1.8V. Therefore add the possibility for the
> > > generic bridge driver to enable supplies provided by the hw-specific
> > > drivers.
> > > 
> > > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> > 
> > does this look ok now?
> > 
> > And as we talked about in Chemnitz, who will be taking such bridge-related
> > changes, as you mentioned some last bridge-patches going through Thierry.
> 
> Sorry, I had completely missed this.
> 
> > > ---
> > > changes since v2:
> > > - rename supplies to the names found in the hdmi IP databook
> > > changes since v1:
> > > - follow suggestion from Russell King to keep regulator handling local
> > > 
> > >   to the rockchip implementation for the time being and only generalize
> > >   when a real second implementation needs regulator handling
> > >  
> > >  .../devicetree/bindings/drm/bridge/dw_hdmi.txt     |  5 ++++
> > >  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        | 32
> > > 
> > > +++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt index
> > > a905c14..bb74640 100644
> > > --- a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > +++ b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > @@ -22,6 +22,11 @@ Optional properties
> > > 
> > >  - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
> > >  - clocks, clock-names: phandle to the HDMI CEC clock, name should be
> > >  "cec"
> > > 
> > > +Optional supplies:
> > > +rockchip,rk3288-dw-hdmi handles two optional power supplies:
> > > +- vp-supply: 1.0V power supply
> > > +- vph-supply: 1.8V power supply
> 
> If this is specific to the Rockchip implementation, shouldn't this go
> into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> could then simply go into the Rockchip DRM tree.

actually, we determined that the supply names are universal to the IP (both in 
imx and rockchip and probably more if there are more users out there). Just 
Russell requested that we don't pollute the generic code until necessary, as 
it looks like the supply of those is somehow handled internally on the imx.


Heiko


From thierry.reding at gmail.com  Fri Jun  5 05:23:14 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Fri, 5 Jun 2015 14:23:14 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <23123577.mOoqGCAPdL@diego>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
Message-ID: <20150605122311.GA759@ulmo.nvidia.com>

On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> Hi Thierry
> 
> Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> > On Mon, Mar 23, 2015 at 07:17:49PM +0100, Heiko Stuebner wrote:
> > > Hi Philipp,
> > > 
> > > Am Donnerstag, 12. M?rz 2015, 21:45:19 schrieb Heiko Stuebner:
> > > > At least the Rockchip variant of the dw_hdmi can have controllable power
> > > > supplies providing 1.0 and 1.8V. Therefore add the possibility for the
> > > > generic bridge driver to enable supplies provided by the hw-specific
> > > > drivers.
> > > > 
> > > > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> > > 
> > > does this look ok now?
> > > 
> > > And as we talked about in Chemnitz, who will be taking such bridge-related
> > > changes, as you mentioned some last bridge-patches going through Thierry.
> > 
> > Sorry, I had completely missed this.
> > 
> > > > ---
> > > > changes since v2:
> > > > - rename supplies to the names found in the hdmi IP databook
> > > > changes since v1:
> > > > - follow suggestion from Russell King to keep regulator handling local
> > > > 
> > > >   to the rockchip implementation for the time being and only generalize
> > > >   when a real second implementation needs regulator handling
> > > >  
> > > >  .../devicetree/bindings/drm/bridge/dw_hdmi.txt     |  5 ++++
> > > >  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c        | 32
> > > > 
> > > > +++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > > b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt index
> > > > a905c14..bb74640 100644
> > > > --- a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > > +++ b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
> > > > @@ -22,6 +22,11 @@ Optional properties
> > > > 
> > > >  - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
> > > >  - clocks, clock-names: phandle to the HDMI CEC clock, name should be
> > > >  "cec"
> > > > 
> > > > +Optional supplies:
> > > > +rockchip,rk3288-dw-hdmi handles two optional power supplies:
> > > > +- vp-supply: 1.0V power supply
> > > > +- vph-supply: 1.8V power supply
> > 
> > If this is specific to the Rockchip implementation, shouldn't this go
> > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > could then simply go into the Rockchip DRM tree.
> 
> actually, we determined that the supply names are universal to the IP (both in 
> imx and rockchip and probably more if there are more users out there). Just 
> Russell requested that we don't pollute the generic code until necessary, as 
> it looks like the supply of those is somehow handled internally on the imx.

If it's universal then there should be no need to mention the Rockchip
compatible specifically. Also, it might be better to submit this as two
separate patches, one for the binding and another for the driver.

I could extract the DT binding piece myself and apply only that, then
somebody else can apply the Rockchip change to that driver separately.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150605/67ff55f7/attachment-0001.sig>

From wxt at rock-chips.com  Fri Jun  5 08:11:41 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 23:11:41 +0800
Subject: [PATCH v3 0/3]     ARM: rockchip: fix the SMP
Message-ID: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>

    Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 08:11:42 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 23:11:42 +0800
Subject: [PATCH v3 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433517104-7595-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    reset_control_deassert

This is needed for stressing CPU up/down, as per:
    cd /sys/devices/system/cpu/
    for i in $(seq 1000); do
        echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
    .......

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..25da16f 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -88,18 +88,24 @@ static int pmu_set_power_domain(int pd, bool on)
 			return PTR_ERR(rstc);
 		}
 
-		if (on)
-			reset_control_deassert(rstc);
-		else
+		if (!on)
 			reset_control_assert(rstc);
 
-		reset_control_put(rstc);
-	}
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			reset_control_put(rstc);
+			return ret;
+		}
 
-	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
-	if (ret < 0) {
-		pr_err("%s: could not update power domain\n", __func__);
-		return ret;
+		if (on)
+			reset_control_deassert(rstc);
+	} else {
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			return ret;
+		}
 	}
 
 	ret = -1;
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 08:11:43 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 23:11:43 +0800
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433517104-7595-3-git-send-email-wxt@rock-chips.com>

In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
WFI/WFE state.
we can delay 1ms to ensure the CPU enter WFI/WFE state.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 25da16f..6672fdd 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -325,6 +325,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 08:11:44 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Fri,  5 Jun 2015 23:11:44 +0800
Subject: [PATCH v3 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433517104-7595-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
Although there is a check, it's no matter.

CHECK: usleep_range is preferred over udelay; see
Documentation/timers/timers-howto.txt
+167udelay(10);
total: 0 errors, 0 warnings, 1 checks, 362 lines checked

 Changes in v3:
    - FIx the PATCH v2, it doesn't work on chromium 3.14.

 Changes in v2:
    - As Kever points out, Fix the subject typo WIF/WFI in PATCH [2/3].
    - As Heiko suggestion, re-adjust the cpu on/off flow in PATCH [1/3].
    - Use the checkpatch.pl -f --subjective to check in PATCH [3/3].

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 6672fdd..ac9173e 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -113,7 +113,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -137,7 +137,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -156,7 +156,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		udelay(10);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -335,7 +335,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -348,4 +348,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From heiko at sntech.de  Fri Jun  5 08:52:48 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 17:52:48 +0200
Subject: [PATCH v3 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433517104-7595-2-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-2-git-send-email-wxt@rock-chips.com>
Message-ID: <1744325.yNd0r8SV4R@diego>

Hi Caesar,

Am Freitag, 5. Juni 2015, 23:11:42 schrieb Caesar Wang:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
> 
> In general, the correct flow is:
> 
> CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
> CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     reset_control_deassert
> 
> This is needed for stressing CPU up/down, as per:
>     cd /sys/devices/system/cpu/
>     for i in $(seq 1000); do
>         echo "================= $i ============"
>         for j in $(seq 100); do
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> cpu3/online)" != "000"" ]] echo 0 > cpu1/online
>                 echo 0 > cpu2/online
>                 echo 0 > cpu3/online
>             done
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat
> cpu3/online)" != "111" ]]; do echo 1 > cpu1/online
>                 echo 1 > cpu2/online
>                 echo 1 > cpu3/online
>             done
>         done
>     done
> 
> The following is reproducile log:
>     [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>     [34466.186824] Disabling non-boot CPUs ...
>     [34466.187509] CPU1: shutdown
>     [34466.188672] CPU2: shutdown
>     [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP
> on cpu 0 .......
> 
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---

could we do this something like the shown below instead?
Here the deassertion of the reset really happens after we are sure the
power-domain is on


-------------- 8< ---------------
diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..ee5dbad6 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
 static int pmu_set_power_domain(int pd, bool on)
 {
 	u32 val = (on) ? 0 : BIT(pd);
+	struct reset_control *rstc = rockchip_get_core_reset(pd);
 	int ret;
 
 	/*
@@ -80,20 +81,16 @@ static int pmu_set_power_domain(int pd, bool on)
 	 * processor is powered down.
 	 */
 	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
-		struct reset_control *rstc = rockchip_get_core_reset(pd);
-
+		/* We only require the reset on the RK3288 at the moment */
 		if (IS_ERR(rstc)) {
 			pr_err("%s: could not get reset control for core %d\n",
 			       __func__, pd);
 			return PTR_ERR(rstc);
 		}
 
-		if (on)
-			reset_control_deassert(rstc);
-		else
+		if (!on)
 			reset_control_assert(rstc);
 
-		reset_control_put(rstc);
 	}
 
 	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
@@ -112,6 +109,12 @@ static int pmu_set_power_domain(int pd, bool on)
 		}
 	}
 
+	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
+			reset_control_deassert(rstc);
+
+	if (!IS_ERR(rstc))
+		reset_control_put(rstc);
+
 	return 0;
 }
 
-------------- 8< ---------------


From heiko at sntech.de  Fri Jun  5 09:17:09 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 18:17:09 +0200
Subject: [PATCH v3 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1744325.yNd0r8SV4R@diego>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-2-git-send-email-wxt@rock-chips.com>
 <1744325.yNd0r8SV4R@diego>
Message-ID: <2303499.bZIqGxfG9l@diego>

Hi Caesar,

Am Freitag, 5. Juni 2015, 17:52:48 schrieb Heiko St?bner:
> could we do this something like the shown below instead?
> Here the deassertion of the reset really happens after we are sure the
> power-domain is on
 
As you mention in the gerrit cl that the hang does happen when you
deassert the reset before the power-domain wait, ignore my last message please 
:-)

But please make sure to also provide a changelog to the list submissions in 
the future.


Thanks
Heiko



From dianders at chromium.org  Fri Jun  5 09:28:42 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 5 Jun 2015 09:28:42 -0700
Subject: [PATCH v3 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433517104-7595-2-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-2-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=WTGz9SYGap5V7YAWdJy_pOScivo6x66vni2-fW5Y7xNQ@mail.gmail.com>

Caesar,

On Fri, Jun 5, 2015 at 8:11 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
>
> In general, the correct flow is:
>
> CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))

Add: "ensure power domain is on" to this list.

> CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     reset_control_deassert

Add: "ensure power domain is on" to this list.

Adding the "ensure power domain is on" step helps document that patch
set version 2 is not what you want and that you thought about it.


> @@ -88,18 +88,24 @@ static int pmu_set_power_domain(int pd, bool on)
>                         return PTR_ERR(rstc);
>                 }
>
> -               if (on)
> -                       reset_control_deassert(rstc);
> -               else
> +               if (!on)
>                         reset_control_assert(rstc);
>
> -               reset_control_put(rstc);
> -       }
> +               ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> +               if (ret < 0) {
> +                       pr_err("%s: could not update power domain\n", __func__);
> +                       reset_control_put(rstc);
> +                       return ret;
> +               }
>
> -       ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> -       if (ret < 0) {
> -               pr_err("%s: could not update power domain\n", __func__);
> -               return ret;
> +               if (on)
> +                       reset_control_deassert(rstc);

I think you need a "reset_control_put(rstc);" here in the non-error case.

Otherwise this looks reasonable to me and you can add my Reviewed-by
tag.  I'll also kick off some tests with this series today to confirm
as well.

-Doug


From wxt at rock-chips.com  Fri Jun  5 10:03:52 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:03:52 +0800
Subject: [PATCH v4 0/3]     ARM: rockchip: fix the SMP
Message-ID: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>

    Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:03:53 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:03:53 +0800
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
References: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523836-4299-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    ensure power domain is on
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    reset_control_deassert
    ensure power domain is on

This is needed for stressing CPU up/down, as per:
    cd /sys/devices/system/cpu/
    for i in $(seq 1000); do
        echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
    .......

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Doug Anderson <dianders at chromium.org>
---

 arch/arm/mach-rockchip/platsmp.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..a297b86 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -88,18 +88,26 @@ static int pmu_set_power_domain(int pd, bool on)
 			return PTR_ERR(rstc);
 		}
 
+		if (!on)
+			reset_control_assert(rstc);
+
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			reset_control_put(rstc);
+			return ret;
+		}
+
 		if (on)
 			reset_control_deassert(rstc);
-		else
-			reset_control_assert(rstc);
 
 		reset_control_put(rstc);
-	}
-
-	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
-	if (ret < 0) {
-		pr_err("%s: could not update power domain\n", __func__);
-		return ret;
+	} else {
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			return ret;
+		}
 	}
 
 	ret = -1;
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:03:54 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:03:54 +0800
Subject: [PATCH v4 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
References: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523836-4299-3-git-send-email-wxt@rock-chips.com>

In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
WFI/WFE state.
we can delay 1ms to ensure the CPU enter WFI/WFE state.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index a297b86..d809fbc 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -327,6 +327,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:03:55 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:03:55 +0800
Subject: [PATCH v4 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
References: <1433523836-4299-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523836-4299-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
Although there is a check, it's no matter.

CHECK: usleep_range is preferred over udelay; see
Documentation/timers/timers-howto.txt
+167udelay(10);
total: 0 errors, 0 warnings, 1 checks, 362 lines checked

 Changes in v4:
    - Add reset_control_put(rstc) for the non-error case.
    - Fix commit information in PATCH [1/3]

 Changes in v3:
    - FIx the PATCH v2, it doesn't work on chromium 3.14.

 Changes in v2:
    - As Kever points out, Fix the subject typo WIF/WFI in PATCH [2/3].
    - As Heiko suggestion, re-adjust the cpu on/off flow in PATCH [1/3].
    - Use the checkpatch.pl -f --subjective to check in PATCH [3/3].

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index d809fbc..63e9c7c 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -115,7 +115,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -139,7 +139,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -158,7 +158,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		udelay(10);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -337,7 +337,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -350,4 +350,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:05:20 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:05:20 +0800
Subject: [PATCH v4 0/3]     ARM: rockchip: fix the SMP
Message-ID: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>

    Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 36 ++++++++++++++++++++++++------------
 1 file changed, 24 insertions(+), 12 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:05:21 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:05:21 +0800
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523923-4755-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    ensure power domain is on
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    reset_control_deassert
    ensure power domain is on

This is needed for stressing CPU up/down, as per:
    cd /sys/devices/system/cpu/
    for i in $(seq 1000); do
        echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
    .......

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Doug Anderson <dianders at chromium.org>
---

 arch/arm/mach-rockchip/platsmp.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..a297b86 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -88,18 +88,26 @@ static int pmu_set_power_domain(int pd, bool on)
 			return PTR_ERR(rstc);
 		}
 
+		if (!on)
+			reset_control_assert(rstc);
+
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			reset_control_put(rstc);
+			return ret;
+		}
+
 		if (on)
 			reset_control_deassert(rstc);
-		else
-			reset_control_assert(rstc);
 
 		reset_control_put(rstc);
-	}
-
-	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
-	if (ret < 0) {
-		pr_err("%s: could not update power domain\n", __func__);
-		return ret;
+	} else {
+		ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
+		if (ret < 0) {
+			pr_err("%s: could not update power domain\n", __func__);
+			return ret;
+		}
 	}
 
 	ret = -1;
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:05:22 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:05:22 +0800
Subject: [PATCH v4 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523923-4755-3-git-send-email-wxt@rock-chips.com>

In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
WFI/WFE state.
we can delay 1ms to ensure the CPU enter WFI/WFE state.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index a297b86..d809fbc 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -327,6 +327,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Fri Jun  5 10:05:23 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sat,  6 Jun 2015 01:05:23 +0800
Subject: [PATCH v4 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433523923-4755-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
Although there is a check, it's no matter.

CHECK: usleep_range is preferred over udelay; see
Documentation/timers/timers-howto.txt
+167udelay(10);
total: 0 errors, 0 warnings, 1 checks, 362 lines checked

 Changes in v4:
    - Add reset_control_put(rstc) for the non-error case.
    - Fix commit information in PATCH [1/3]

 Changes in v3:
    - FIx the PATCH v2, it doesn't work on chromium 3.14.

 Changes in v2:
    - As Kever points out, Fix the subject typo WIF/WFI in PATCH [2/3].
    - As Heiko suggestion, re-adjust the cpu on/off flow in PATCH [1/3].
    - Use the checkpatch.pl -f --subjective to check in PATCH [3/3].

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
---

 arch/arm/mach-rockchip/platsmp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index d809fbc..63e9c7c 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -115,7 +115,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -139,7 +139,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -158,7 +158,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		udelay(10);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -337,7 +337,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -350,4 +350,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From heiko at sntech.de  Fri Jun  5 10:05:43 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 19:05:43 +0200
Subject: [PATCH v4 1/3] dt-bindings: describe dw_hdmi supplies
Message-ID: <1707049.JEvfTcofKv@diego>

The Designware HDMI block has two supplies for 1.0 and 1.8V. Not all IP
implementations expose or want to use these, so they remain optional.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
---
changes since v3:
- split generic dt-bindings and rockchip implementation
- add Ack from Philipp Zabel
changes since v2:
- rename supplies to the names found in the hdmi IP databook

 Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
index a905c14..ba42d89 100644
--- a/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
+++ b/Documentation/devicetree/bindings/drm/bridge/dw_hdmi.txt
@@ -22,6 +22,10 @@ Optional properties
 - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
 - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
 
+Optional supplies:
+- vp-supply: 1.0V power supply
+- vph-supply: 1.8V power supply
+
 Example:
 	hdmi: hdmi at 0120000 {
 		compatible = "fsl,imx6q-hdmi";
-- 
2.1.4




From heiko at sntech.de  Fri Jun  5 10:06:38 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 19:06:38 +0200
Subject: [PATCH v4 2/3] drm/rockchip: implement dw_hdmi supplies for the
 Rockchip implementation
In-Reply-To: <1707049.JEvfTcofKv@diego>
References: <1707049.JEvfTcofKv@diego>
Message-ID: <17068264.uLYIadrGJJ@diego>

The Rockchip implementation of the IP exposes the supplies outside and
expects them to be supplied by a pmic. So implement regulator handling
for them.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
---
changes since v3:
- split generic dt-bindings and rockchip implementation
- add Ack from Philipp Zabel
changes since v2:
- rename supplies to the names found in the hdmi IP databook
changes since v1:
- follow suggestion from Russell King to keep regulator handling local
  to the rockchip implementation for the time being and only generalize
  when a real second implementation needs regulator handling

 drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 32 ++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 80d6fc8..9c003fa 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
@@ -28,6 +29,9 @@ struct rockchip_hdmi {
 	struct device *dev;
 	struct regmap *regmap;
 	struct drm_encoder encoder;
+	struct regulator_bulk_data supplies[2];
+	int nsupplies;
+	bool supplies_enabled;
 };
 
 #define to_rockchip_hdmi(x)	container_of(x, struct rockchip_hdmi, x)
@@ -179,6 +183,12 @@ static struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
 
 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
 {
+	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
+
+	if (hdmi->nsupplies > 0 && hdmi->supplies_enabled) {
+		regulator_bulk_disable(hdmi->nsupplies, hdmi->supplies);
+		hdmi->supplies_enabled = false;
+	}
 }
 
 static bool
@@ -199,7 +209,16 @@ static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
 {
 	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
 	u32 val;
-	int mux;
+	int mux, ret;
+
+	if (hdmi->nsupplies > 0 && !hdmi->supplies_enabled) {
+		ret = regulator_bulk_enable(hdmi->nsupplies, hdmi->supplies);
+		if (ret) {
+			dev_err(hdmi->dev, "could not enable hdmi analog supplies\n");
+			return;
+		}
+		hdmi->supplies_enabled = true;
+	}
 
 	mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
 	if (mux)
@@ -275,6 +294,17 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
 	if (!iores)
 		return -ENXIO;
 
+	hdmi->supplies[0].supply = "vp";
+	hdmi->supplies[1].supply = "vph";
+	hdmi->nsupplies = 2;
+
+	ret = devm_regulator_bulk_get(hdmi->dev,
+				      hdmi->nsupplies, hdmi->supplies);
+	if (ret == -EPROBE_DEFER)
+		return ret;
+	if (ret)
+		hdmi->nsupplies = 0;
+
 	platform_set_drvdata(pdev, hdmi);
 
 	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
-- 
2.1.4




From heiko at sntech.de  Fri Jun  5 10:07:34 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 05 Jun 2015 19:07:34 +0200
Subject: [PATCH v4 3/3] ARM: dts: rockchip: add hdmi analog power supplies to
 rk3288 boards
In-Reply-To: <1707049.JEvfTcofKv@diego>
References: <1707049.JEvfTcofKv@diego>
Message-ID: <2174509.z9PNBvxjWd@diego>

Add the recently added hdmi power supplies to evb and firefly boards.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
changes since v3:
- add entries for popmetal board

 arch/arm/boot/dts/rk3288-evb.dtsi     | 2 ++
 arch/arm/boot/dts/rk3288-firefly.dtsi | 2 ++
 arch/arm/boot/dts/rk3288-popmetal.dts | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi
index 844a6fb..a57fbe3 100644
--- a/arch/arm/boot/dts/rk3288-evb.dtsi
+++ b/arch/arm/boot/dts/rk3288-evb.dtsi
@@ -172,6 +172,8 @@
 };
 
 &hdmi {
 	ddc-i2c-bus = <&i2c5>;
+	vp-supply = <&vdd10_lcd>;
+	vph-supply = <&vcc18_lcd>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi
index 0b42372..68068d9 100644
--- a/arch/arm/boot/dts/rk3288-firefly.dtsi
+++ b/arch/arm/boot/dts/rk3288-firefly.dtsi
@@ -196,6 +196,8 @@
 };
 
 &hdmi {
 	ddc-i2c-bus = <&i2c5>;
+	vp-supply = <&vdd10_lcd>;
+	vph-supply = <&vcc18_lcd>;
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/rk3288-popmetal.dts b/arch/arm/boot/dts/rk3288-popmetal.dts
index d582811..98f4d77 100644
--- a/arch/arm/boot/dts/rk3288-popmetal.dts
+++ b/arch/arm/boot/dts/rk3288-popmetal.dts
@@ -141,6 +141,8 @@
 
 &hdmi {
 	ddc-i2c-bus = <&i2c5>;
+	vp-supply = <&vdd10_lcd>;
+	vph-supply = <&vcc18_lcd>;
 	status = "okay";
 };
 
-- 
2.1.4




From dianders at chromium.org  Fri Jun  5 10:49:14 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 5 Jun 2015 10:49:14 -0700
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433517104-7595-3-git-send-email-wxt@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-3-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>

Caesar,

On Fri, Jun 5, 2015 at 8:11 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
> WFI/WFE state.
> we can delay 1ms to ensure the CPU enter WFI/WFE state.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> ---
>
>  arch/arm/mach-rockchip/platsmp.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 25da16f..6672fdd 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -325,6 +325,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
>  #ifdef CONFIG_HOTPLUG_CPU
>  static int rockchip_cpu_kill(unsigned int cpu)
>  {
> +       /* ensure CPU can enter the WFI/WFE state */
> +       mdelay(1);

This is a pretty weak assurance.  Is there any stronger assurance you
can give that we're in WFI/WFE state and won't come out of it?

Do you actually see problems if you power off a CPU when it's not in
WFI/WFE state?

...so I _think_ I see the path that is happening here and what you're
trying to handle.  Specifically, I see:

On dying CPU:
1. cpu_die() calls 'complete(&cpu_died)'
2. cpu_die() calls 'smp_ops.cpu_die(cpu)' AKA rockchip_cpu_die()
3. rockchip_cpu_die() does a bit more cache flushing before looping in
cpu_do_idle()

The problem is that the moment the completion happens in step #1 above
the dying CPU can be killed.  ...so you're trying to make sure the
dying CPU makes it to cpu_do_idle().  In that case a fixed mdelay(1)
might be OK since the time that the CPU takes to run through a few
instructions (with no interrupts) is pretty predictable.  It would be
really nice if the commit message went through all this, though.

...but is there any chance that cpu_do_idle() could somehow return?
We shouldn't send any events since we've marked the core offline, but
perhaps some per-core interrupt (arch timer?) that didn't get
migrated?


-Doug


From linux at arm.linux.org.uk  Fri Jun  5 11:29:47 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Fri, 5 Jun 2015 19:29:47 +0100
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-3-git-send-email-wxt@rock-chips.com>
 <CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>
Message-ID: <20150605182947.GN7557@n2100.arm.linux.org.uk>

On Fri, Jun 05, 2015 at 10:49:14AM -0700, Doug Anderson wrote:
> On Fri, Jun 5, 2015 at 8:11 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> > In idle mode, core1/2/3 of Cortex-A17 should be either power off or in
> > WFI/WFE state.
> > we can delay 1ms to ensure the CPU enter WFI/WFE state.
> >
> > Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> > ---
> >
> >  arch/arm/mach-rockchip/platsmp.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> > index 25da16f..6672fdd 100644
> > --- a/arch/arm/mach-rockchip/platsmp.c
> > +++ b/arch/arm/mach-rockchip/platsmp.c
> > @@ -325,6 +325,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
> >  #ifdef CONFIG_HOTPLUG_CPU
> >  static int rockchip_cpu_kill(unsigned int cpu)
> >  {
> > +       /* ensure CPU can enter the WFI/WFE state */
> > +       mdelay(1);
> 
> This is a pretty weak assurance.  Is there any stronger assurance you
> can give that we're in WFI/WFE state and won't come out of it?
> 
> Do you actually see problems if you power off a CPU when it's not in
> WFI/WFE state?

I really don't like to see platforms pulling crap tricks in their
CPU hotunplug code like this.  If there's something wrong with the
generic code, then the generic code needs to be fixed, not worked
around in platform code.

> ...so I _think_ I see the path that is happening here and what you're
> trying to handle.  Specifically, I see:
> 
> On dying CPU:
> 1. cpu_die() calls 'complete(&cpu_died)'
> 2. cpu_die() calls 'smp_ops.cpu_die(cpu)' AKA rockchip_cpu_die()
> 3. rockchip_cpu_die() does a bit more cache flushing before looping in
> cpu_do_idle()
> 
> The problem is that the moment the completion happens in step #1 above
> the dying CPU can be killed.  ...so you're trying to make sure the
> dying CPU makes it to cpu_do_idle().  In that case a fixed mdelay(1)
> might be OK since the time that the CPU takes to run through a few
> instructions (with no interrupts) is pretty predictable.  It would be
> really nice if the commit message went through all this, though.
> 
> ...but is there any chance that cpu_do_idle() could somehow return?
> We shouldn't send any events since we've marked the core offline, but
> perhaps some per-core interrupt (arch timer?) that didn't get
> migrated?

How this is supposed to work is:

	CPU requesting death		CPU dying
	stop_machine(take_down_cpu)
					take_down_cpu()
					-__cpu_disable()
					- platform_cpu_disable()
					- marks CPU offline
					- migrates IRQs away
					- caches flushed
					- tlbs flushed
	__cpu_die()			- processes migrated away
	-wait_for_completion_timeout()	-timekeeping migrated away
					returns to idle loop
					arch_cpu_idle_dead()
					-cpu_die()
					- idle_task_exit()
					- flush_cache_louis()

At this point, dirty cache lines which matter are flushed from the
dying CPUs cache.  However, we still need the dying CPU to be
coherent for the next step, which is to issue the completion.

					- complete()
					- flush_cache_louis()

At some point during the above, the completion becomes visible to
the other CPU, and it continues its execution.

	-pr_notice()
	-platform_cpu_kill()		- smp_ops.cpu_die()

The precise ordering of smp_ops.cpu_die() vs platform_cpu_kill() is
pretty much indeterminant, and is subject to scheduling effects which
could delay the requesting CPU.

Now, the problem is, from what ARM has been saying, that cache lines
can get migrated to the dying CPU which may contain the "master" copy
of the data, which means that when the dying CPU actually exits
coherency, that data is lost to the rest of the system.

Ideally, what we would like to do is to exit coherency earlier, and
then have some notification mechanism between the dying CPU and the
rest of the system to say that it's finished exiting coherency.
However, we face several issues.

1) v7_coherency_exit() is specific to v7 CPUs and can't be used by
   generic code.

2) we have no way to perform that notification reliably once
   coherency has been exited.

There's other reasons we need to change the notification mechanism,
one of them is that completions use RCU, and RCU isn't actually valid
in this context - and we can't make it valid because the dying CPU
might loose power at any moment after it's called complete().

Paul McKenny created what was a generic infrastructure for this
notification, but I object to it on principle using atomic_t... and
if we've exited coherency (as we would want to), it won't work
because it makes use of atomic_cmpxchg() on the dying CPU.

I've been working on a solution to use an IPI to notify from the
dying CPU, but that's fraught because of the separation of the IRQ
controller code from the architecture code, and we now have spinlocks
in the IPI-raising path due to the big.LITTLE stuff - and spinlocks
need coherency to be working.

So, we're actually in a very sticky position over taking CPUs offline.
It seems to be something that the ARM architecture and kernel
architecture doesn't actually allow to be done safely.  So much so,
that in a similar way to the original Keystone 2 physical address
switch, I'm tempted to make taking a CPU offline taint the kernel!

We're going to end up with tainted kernels through this path when Paul
pushes his RCU correctness patches anyway anyway, so it's just a
matter of the inevitable taint happening sooner or later.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From dianders at chromium.org  Fri Jun  5 13:24:40 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 5 Jun 2015 13:24:40 -0700
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <20150605182947.GN7557@n2100.arm.linux.org.uk>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-3-git-send-email-wxt@rock-chips.com>
 <CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>
 <20150605182947.GN7557@n2100.arm.linux.org.uk>
Message-ID: <CAD=FV=UamkH+RHmHHVzGKZda_w0teGBdfcH-LbCKqyp2q1OVqA@mail.gmail.com>

Russell,

On Fri, Jun 5, 2015 at 11:29 AM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> 1) v7_coherency_exit() is specific to v7 CPUs and can't be used by
>    generic code.

Oh, I see.  So (I think) you're saying that perhaps the reason that
Caesar needed his patch was that he needed the dying processor to
execute v7_exit_coherency_flush(), NOT that he needed the dying
processor to be in WFI/WFE.  That actually makes a lot more sense to
me!  :)  Thanks a lot for pointing that out, it's very helpful.


> So, we're actually in a very sticky position over taking CPUs offline.
> It seems to be something that the ARM architecture and kernel
> architecture doesn't actually allow to be done safely.  So much so,
> that in a similar way to the original Keystone 2 physical address
> switch, I'm tempted to make taking a CPU offline taint the kernel!

Wow, that's going to suck.  So if you want to suspend / resume you
need to taint your kernel.  So much for saving the planet by going
into suspend...  ...or are you thinking that it won't taint the kernel
when the kernel takes CPUs offline for suspend/resume purposes?  ...or
are you thinking you've some solution that works for suspend/resume
that doesn't work for the general cpu offlining problem?  I'd be very
interested to hear...


I know I'm not a maintainer, but if I were and I knew that lots of
smart people had thought about the problem of CPU offlining and they
didn't have a solution and I could make my platform 99.99999999%
reliable by allowing a very safe mdelay(1) where I had a pretty strong
guarantee that the 1ms was enough time, I would probably accept that
code...


So since I'm not a maintainer and I certainly couldn't ack such code,
I would certainly be happy to add my Reviewed-by to Caesar's patch if
he changed it mention that he needed to make sure that
v7_exit_coherency_flush() in rockchip_cpu_die() executed in time.


-Doug


From dianders at chromium.org  Fri Jun  5 13:55:20 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 5 Jun 2015 13:55:20 -0700
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433523923-4755-2-git-send-email-wxt@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
 <1433523923-4755-2-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=XGOVpAA5+NQ8O910T=CPrYKfTseBXfNbR4EkenzDECaQ@mail.gmail.com>

Caesar,

On Fri, Jun 5, 2015 at 10:05 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> +               if (!on)
> +                       reset_control_assert(rstc);
> +
> +               ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> +               if (ret < 0) {
> +                       pr_err("%s: could not update power domain\n", __func__);
> +                       reset_control_put(rstc);
> +                       return ret;
> +               }
> +
>                 if (on)
>                         reset_control_deassert(rstc);
> -               else
> -                       reset_control_assert(rstc);

As Heiko indicated in the previous patchset, he thought it would be
nice to move the 'pmu_power_domain_is_on(pd)' to before you deasserted
reset.  ...but then I pointed out that you tested that in patch set #2
and it didn't work.

Talking to Heiko offline he thought that perhaps you could make
'pmu_power_domain_is_on(pd)' work if you increased your 'udelay(10);'
in rockchip_boot_secondary().  Perhaps the old
'pmu_power_domain_is_on' was acting like an extra bit of delay and
that's why moving it broke things.


I actually went back and tested patch set #2 and it worked for me, so
I couldn't test Heiko's theory.  Could you go and reproduce the
problem with patch set #2 again and then try increasing the udelay()
and see if your problems go away?  If that works, it might be a
slightly better solution.  Note that I think Heiko had a slightly
cleaner version of your patch set #2 that he posted in response to
your patch set #3.


-Doug


From dianders at chromium.org  Fri Jun  5 13:58:14 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 5 Jun 2015 13:58:14 -0700
Subject: [PATCH v4 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433523923-4755-4-git-send-email-wxt@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
 <1433523923-4755-4-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=Xj-j2Fnnch99rzvKpvsrpgaz6ukfM+X87O20B-nHbjkQ@mail.gmail.com>

Caesar,

On Fri, Jun 5, 2015 at 10:05 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> Use the below scripts to check:
> scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
> Although there is a check, it's no matter.
>
> CHECK: usleep_range is preferred over udelay; see
> Documentation/timers/timers-howto.txt
> +167udelay(10);
> total: 0 errors, 0 warnings, 1 checks, 362 lines checked
>
>  Changes in v4:
>     - Add reset_control_put(rstc) for the non-error case.
>     - Fix commit information in PATCH [1/3]
>
>  Changes in v3:
>     - FIx the PATCH v2, it doesn't work on chromium 3.14.
>
>  Changes in v2:
>     - As Kever points out, Fix the subject typo WIF/WFI in PATCH [2/3].
>     - As Heiko suggestion, re-adjust the cpu on/off flow in PATCH [1/3].
>     - Use the checkpatch.pl -f --subjective to check in PATCH [3/3].

The change log should (ideally) be with each patch.  If that's too
hard and you want to put it in one place, please put it in the cover
letter (the 0/3 email).

Also: the change log should be "below the cut".  That is, it should be
below the "---" and above the diffstat.

Other than those problems:

Reviewed-by: Douglas Anderson <dianders at chromium.org>


-Doug


From heiko at sntech.de  Fri Jun  5 16:03:25 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Sat, 06 Jun 2015 01:03:25 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150605122311.GA759@ulmo.nvidia.com>
References: <4184159.j0iXe39dFB@phil> <23123577.mOoqGCAPdL@diego>
 <20150605122311.GA759@ulmo.nvidia.com>
Message-ID: <1590039.lzO65vr8K7@diego>

Hi Thierry

Am Freitag, 5. Juni 2015, 14:23:14 schrieb Thierry Reding:
> On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> > > If this is specific to the Rockchip implementation, shouldn't this go
> > > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > > could then simply go into the Rockchip DRM tree.
> > 
> > actually, we determined that the supply names are universal to the IP
> > (both in imx and rockchip and probably more if there are more users out
> > there). Just Russell requested that we don't pollute the generic code
> > until necessary, as it looks like the supply of those is somehow handled
> > internally on the imx.
> If it's universal then there should be no need to mention the Rockchip
> compatible specifically. Also, it might be better to submit this as two
> separate patches, one for the binding and another for the driver.
> 
> I could extract the DT binding piece myself and apply only that, then
> somebody else can apply the Rockchip change to that driver separately.

so I've sent a v4 where the dt-binding is split off (and without the Rockchip 
specific text), so if you want to take patch1, Mark could take patch2 and I 
would take the dts changes in patch3.


Heiko


From linux at arm.linux.org.uk  Fri Jun  5 16:10:58 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Sat, 6 Jun 2015 00:10:58 +0100
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <23123577.mOoqGCAPdL@diego>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
Message-ID: <20150605231058.GQ7557@n2100.arm.linux.org.uk>

On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> Hi Thierry
> 
> Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> > If this is specific to the Rockchip implementation, shouldn't this go
> > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > could then simply go into the Rockchip DRM tree.
> 
> actually, we determined that the supply names are universal to the IP
> (both in imx and rockchip and probably more if there are more users
> out there). Just Russell requested that we don't pollute the generic
> code until necessary, as it looks like the supply of those is somehow
> handled internally on the imx.

Why do you think it's universal?

Let's start from the beginning, before we create something that's not
representative of the hardware.

dw_hdmi actually drives two pieces of hardware - the HDMI transmitter,
and a separate hardware block, the HDMI phy.

There are at least two possible HDMI phys referenced in the iMX
documentation - there is one called HEAC which doesn't appear in iMX
devices afaik, and the one which does, which is a 3D phy.

The 3D phy top level IO diagram does have VPH and VP power supplies,
but it also has VP_FILT0, VP_FILT1, VP_FILT2, VP_FILT3 and GD labelled
up as "Power supply signals".  Where they connect to in the rest of the
system - or whether they are connected - is undocumented.

The HDMI transmitter itself is not documented what it's supplies
actually are.

So, what we currently have in DT for dw_hdmi is something which doesn't
_quite_ reflect the hardware right now, and to go adding VP and VPH
supplies to the generic binding is wrong - it doesn't follow the
hardware structure detailed in the iMX documentation I have.

As the Rockchip documentation is not available, I can't comment whether
it would be current proposal is appropriate for Rockchip or not, which
is why I haven't commented on this other than saying that it's not
appropriate to be a generic dw_hdmi binding.

If we wanted to model this correctly, then for iMX, I would suggest
that the HDMI phy should be modelled in DT, and _all_ the six VP*
supplies are modelled - and we should assume that "GD" is a "power
good" signal, though we don't know that for certain.

What we also don't know on iMX6 is what voltages any of these are
supplied with.

So, as we don't have much certainty here, and we know that adding it
to what is the HDMI transmitter would be wrong, I'd suggest not
modelling it in a generic way at present.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From wxt at rock-chips.com  Sat Jun  6 19:51:54 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 07 Jun 2015 10:51:54 +0800
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <CAD=FV=XGOVpAA5+NQ8O910T=CPrYKfTseBXfNbR4EkenzDECaQ@mail.gmail.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>	<1433523923-4755-2-git-send-email-wxt@rock-chips.com>
 <CAD=FV=XGOVpAA5+NQ8O910T=CPrYKfTseBXfNbR4EkenzDECaQ@mail.gmail.com>
Message-ID: <5573B1CA.1050204@rock-chips.com>



? 2015?06?06? 04:55, Doug Anderson ??:
> Caesar,
>
> On Fri, Jun 5, 2015 at 10:05 AM, Caesar Wang <wxt at rock-chips.com> wrote:
>> +               if (!on)
>> +                       reset_control_assert(rstc);
>> +
>> +               ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>> +               if (ret < 0) {
>> +                       pr_err("%s: could not update power domain\n", __func__);
>> +                       reset_control_put(rstc);
>> +                       return ret;
>> +               }
>> +
>>                  if (on)
>>                          reset_control_deassert(rstc);
>> -               else
>> -                       reset_control_assert(rstc);
> As Heiko indicated in the previous patchset, he thought it would be
> nice to move the 'pmu_power_domain_is_on(pd)' to before you deasserted
> reset.  ...but then I pointed out that you tested that in patch set #2
> and it didn't work.
>
> Talking to Heiko offline he thought that perhaps you could make
> 'pmu_power_domain_is_on(pd)' work if you increased your 'udelay(10);'
> in rockchip_boot_secondary().  Perhaps the old
> 'pmu_power_domain_is_on' was acting like an extra bit of delay and
> that's why moving it broke things.
>
>
> I actually went back and tested patch set #2 and it worked for me, so
> I couldn't test Heiko's theory.  Could you go and reproduce the
> problem with patch set #2 again and then try increasing the udelay()
> and see if your problems go away?  If that works, it might be a
> slightly better solution.  Note that I think Heiko had a slightly
> cleaner version of your patch set #2 that he posted in response to
> your patch set #3.

@@ -150,13 +159,15 @@ static int __cpuinit 
rockchip_boot_secondary(unsigned int cpu,
                  * sram_base_addr + 4: 0xdeadbeaf
                  * sram_base_addr + 8: start address for pc
                  * */
-               udelay(10);
+               udelay(20);

I increased the 'udelay(20)' or 'udelay(50)' in rockchip_boot_secondary().
Set#2 also can repro this issue over 22600 cycles with testing scripts. 
(about 1 hours)

log:
================= 226 ============
[ 4069.134419] CPU1: shutdown
[ 4069.164431] CPU2: shutdown
[ 4069.204475] CPU3: shutdown
......
[ 4072.454453] CPU1: shutdown
[ 4072.504436] CPU2: shutdown
[ 4072.554426] CPU3: shutdown
[ 4072.577827] CPU1: Booted secondary processor
[ 4072.582611] CPU2: Booted secondary processor
[ 4072.587426] CPU3: Booted secondary processor
<hang>

The set #4 will be better work.

>
> -Doug
>
>
>

-- 
Thanks,
- Caesar




From dianders at chromium.org  Sat Jun  6 20:43:04 2015
From: dianders at chromium.org (Doug Anderson)
Date: Sat, 6 Jun 2015 20:43:04 -0700
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <5573B1CA.1050204@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
 <1433523923-4755-2-git-send-email-wxt@rock-chips.com>
 <CAD=FV=XGOVpAA5+NQ8O910T=CPrYKfTseBXfNbR4EkenzDECaQ@mail.gmail.com>
 <5573B1CA.1050204@rock-chips.com>
Message-ID: <CAD=FV=VswV+MAgYr084VOxQynHrL1fdwnVb4b_W_bHUZgoW4mg@mail.gmail.com>

Caesar,

On Sat, Jun 6, 2015 at 7:51 PM, Caesar Wang <wxt at rock-chips.com> wrote:
> @@ -150,13 +159,15 @@ static int __cpuinit rockchip_boot_secondary(unsigned
> int cpu,
>                  * sram_base_addr + 4: 0xdeadbeaf
>                  * sram_base_addr + 8: start address for pc
>                  * */
> -               udelay(10);
> +               udelay(20);
>
> I increased the 'udelay(20)' or 'udelay(50)' in rockchip_boot_secondary().
> Set#2 also can repro this issue over 22600 cycles with testing scripts.
> (about 1 hours)
>
> log:
> ================= 226 ============
> [ 4069.134419] CPU1: shutdown
> [ 4069.164431] CPU2: shutdown
> [ 4069.204475] CPU3: shutdown
> ......
> [ 4072.454453] CPU1: shutdown
> [ 4072.504436] CPU2: shutdown
> [ 4072.554426] CPU3: shutdown
> [ 4072.577827] CPU1: Booted secondary processor
> [ 4072.582611] CPU2: Booted secondary processor
> [ 4072.587426] CPU3: Booted secondary processor
> <hang>
>
> The set #4 will be better work.

OK, I'm OK with this, but I'd like to get Heiko's opinion.

Also:
* Just for kicks, does mdelay(1) work?  I know that's 100x more than
udelay(10), but previously we were actually looping waiting for the
power domain, right?  ...so maybe the old code used to introduce a
pretty big delay.

* Does anyone from the chip design team have any idea why patch set #4
works but patch set #2 doesn't?  I know it's Sunday morning in China
right now, but maybe you could ask Monday?


Thanks!

-Doug


From wxt at rock-chips.com  Sat Jun  6 22:51:24 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 07 Jun 2015 13:51:24 +0800
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <CAD=FV=VswV+MAgYr084VOxQynHrL1fdwnVb4b_W_bHUZgoW4mg@mail.gmail.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>	<1433523923-4755-2-git-send-email-wxt@rock-chips.com>	<CAD=FV=XGOVpAA5+NQ8O910T=CPrYKfTseBXfNbR4EkenzDECaQ@mail.gmail.com>	<5573B1CA.1050204@rock-chips.com>
 <CAD=FV=VswV+MAgYr084VOxQynHrL1fdwnVb4b_W_bHUZgoW4mg@mail.gmail.com>
Message-ID: <5573DBDC.2010204@rock-chips.com>



? 2015?06?07? 11:43, Doug Anderson ??:
> Caesar,
>
> On Sat, Jun 6, 2015 at 7:51 PM, Caesar Wang <wxt at rock-chips.com> wrote:
>> @@ -150,13 +159,15 @@ static int __cpuinit rockchip_boot_secondary(unsigned
>> int cpu,
>>                   * sram_base_addr + 4: 0xdeadbeaf
>>                   * sram_base_addr + 8: start address for pc
>>                   * */
>> -               udelay(10);
>> +               udelay(20);
>>
>> I increased the 'udelay(20)' or 'udelay(50)' in rockchip_boot_secondary().
>> Set#2 also can repro this issue over 22600 cycles with testing scripts.
>> (about 1 hours)
>>
>> log:
>> ================= 226 ============
>> [ 4069.134419] CPU1: shutdown
>> [ 4069.164431] CPU2: shutdown
>> [ 4069.204475] CPU3: shutdown
>> ......
>> [ 4072.454453] CPU1: shutdown
>> [ 4072.504436] CPU2: shutdown
>> [ 4072.554426] CPU3: shutdown
>> [ 4072.577827] CPU1: Booted secondary processor
>> [ 4072.582611] CPU2: Booted secondary processor
>> [ 4072.587426] CPU3: Booted secondary processor
>> <hang>
>>
>> The set #4 will be better work.
> OK, I'm OK with this, but I'd like to get Heiko's opinion.
>
> Also:
> * Just for kicks, does mdelay(1) work?  I know that's 100x more than
OK, it should delay more time.

the mdelay(1) can be work over 50000 cycles, so that should be work.


Perhaps, can we use 'usleep_range(500, 1000)' to work.
Heiko, do you agree with it?

> udelay(10), but previously we were actually looping waiting for the
> power domain, right?  ...so maybe the old code used to introduce a
> pretty big delay.
>
> * Does anyone from the chip design team have any idea why patch set #4
> works but patch set #2 doesn't?  I know it's Sunday morning in China
> right now, but maybe you could ask Monday?
>
>
> Thanks!
>
> -Doug
>
>
>

-- 
Thanks,
- Caesar




From heiko at sntech.de  Sun Jun  7 02:02:18 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Sun, 07 Jun 2015 11:02:18 +0200
Subject: [PATCH v4 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <5573DBDC.2010204@rock-chips.com>
References: <1433523923-4755-1-git-send-email-wxt@rock-chips.com>
 <CAD=FV=VswV+MAgYr084VOxQynHrL1fdwnVb4b_W_bHUZgoW4mg@mail.gmail.com>
 <5573DBDC.2010204@rock-chips.com>
Message-ID: <3887846.0ppL0Y56At@diego>

Hi Caesar, Doug,

Am Sonntag, 7. Juni 2015, 13:51:24 schrieb Caesar Wang:
> ? 2015?06?07? 11:43, Doug Anderson ??:
> > Caesar,
> > 
> > On Sat, Jun 6, 2015 at 7:51 PM, Caesar Wang <wxt at rock-chips.com> wrote:
> >> @@ -150,13 +159,15 @@ static int __cpuinit
> >> rockchip_boot_secondary(unsigned
> >> int cpu,
> >> 
> >>                   * sram_base_addr + 4: 0xdeadbeaf
> >>                   * sram_base_addr + 8: start address for pc
> >>                   * */
> >> 
> >> -               udelay(10);
> >> +               udelay(20);
> >> 
> >> I increased the 'udelay(20)' or 'udelay(50)' in
> >> rockchip_boot_secondary().
> >> Set#2 also can repro this issue over 22600 cycles with testing scripts.
> >> (about 1 hours)
> >> 
> >> log:
> >> ================= 226 ============
> >> [ 4069.134419] CPU1: shutdown
> >> [ 4069.164431] CPU2: shutdown
> >> [ 4069.204475] CPU3: shutdown
> >> ......
> >> [ 4072.454453] CPU1: shutdown
> >> [ 4072.504436] CPU2: shutdown
> >> [ 4072.554426] CPU3: shutdown
> >> [ 4072.577827] CPU1: Booted secondary processor
> >> [ 4072.582611] CPU2: Booted secondary processor
> >> [ 4072.587426] CPU3: Booted secondary processor
> >> <hang>
> >> 
> >> The set #4 will be better work.
> > 
> > OK, I'm OK with this, but I'd like to get Heiko's opinion.
> > 
> > Also:
> > * Just for kicks, does mdelay(1) work?  I know that's 100x more than
> 
> OK, it should delay more time.
> 
> the mdelay(1) can be work over 50000 cycles, so that should be work.
> 
> 
> Perhaps, can we use 'usleep_range(500, 1000)' to work.
> Heiko, do you agree with it?

yep :-)

As I said before, doing

	powerup, deassert_reset, wait_for_powerdomain

feels like it is only moving the problem a bit but is actually only working by 
chance, as my [little bit of :-) ] common sense tells me, that we really only 
should deassert the reset when we're sure that the core has power, i.e.

	powerup, wait_for_powerdomain, deassert_reset

Also, when going down this path, please take a look at the slightly different 
variant I posted as response to v3, as it makes the diff a bit smaller :-)


As for {u/m}delay vs. your usleep_ranges, I don't know if you're allowed to 
sleep in this area. Other architectures only seem to use udelay in __cpu_up 
which calls the smp_secondary_startup callback, like:

- arch/sh/kernel/smp.c
- arch/m32r/kernel/smpboot.c [is even a udelay(1000)
and more


Heiko

> > udelay(10), but previously we were actually looping waiting for the
> > power domain, right?  ...so maybe the old code used to introduce a
> > pretty big delay.
> > 
> > * Does anyone from the chip design team have any idea why patch set #4
> > works but patch set #2 doesn't?  I know it's Sunday morning in China
> > right now, but maybe you could ask Monday?
> > 
> > 
> > Thanks!
> > 
> > -Doug



From wxt at rock-chips.com  Sun Jun  7 21:56:07 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon, 08 Jun 2015 12:56:07 +0800
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <CAD=FV=UamkH+RHmHHVzGKZda_w0teGBdfcH-LbCKqyp2q1OVqA@mail.gmail.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>	<1433517104-7595-3-git-send-email-wxt@rock-chips.com>	<CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>	<20150605182947.GN7557@n2100.arm.linux.org.uk>
 <CAD=FV=UamkH+RHmHHVzGKZda_w0teGBdfcH-LbCKqyp2q1OVqA@mail.gmail.com>
Message-ID: <55752067.2040108@rock-chips.com>



? 2015?06?06? 04:24, Doug Anderson ??:
> Russell,
>
> On Fri, Jun 5, 2015 at 11:29 AM, Russell King - ARM Linux
> <linux at arm.linux.org.uk> wrote:
>> 1) v7_coherency_exit() is specific to v7 CPUs and can't be used by
>>     generic code.
> Oh, I see.  So (I think) you're saying that perhaps the reason that
> Caesar needed his patch was that he needed the dying processor to
> execute v7_exit_coherency_flush(), NOT that he needed the dying
> processor to be in WFI/WFE.  That actually makes a lot more sense to
> me!  :)  Thanks a lot for pointing that out, it's very helpful.
>
>
>> So, we're actually in a very sticky position over taking CPUs offline.
>> It seems to be something that the ARM architecture and kernel
>> architecture doesn't actually allow to be done safely.  So much so,
>> that in a similar way to the original Keystone 2 physical address
>> switch, I'm tempted to make taking a CPU offline taint the kernel!
> Wow, that's going to suck.  So if you want to suspend / resume you
> need to taint your kernel.  So much for saving the planet by going
> into suspend...  ...or are you thinking that it won't taint the kernel
> when the kernel takes CPUs offline for suspend/resume purposes?  ...or
> are you thinking you've some solution that works for suspend/resume
> that doesn't work for the general cpu offlining problem?  I'd be very
> interested to hear...
>
>
> I know I'm not a maintainer, but if I were and I knew that lots of
> smart people had thought about the problem of CPU offlining and they
> didn't have a solution and I could make my platform 99.99999999%
> reliable by allowing a very safe mdelay(1) where I had a pretty strong
> guarantee that the 1ms was enough time, I would probably accept that
> code...
>
>
> So since I'm not a maintainer and I certainly couldn't ack such code,
> I would certainly be happy to add my Reviewed-by to Caesar's patch if
> he changed it mention that he needed to make sure that
> v7_exit_coherency_flush() in rockchip_cpu_die() executed in time.

OK.
The dying processor to execute v7_exit_coherency_flush(),not that the 
dying processor to be in WFI/WFE.

It's needed to enter WFI/WFE state from the ARM refer document when CPU 
down.

But......

Here is my test: (won't to enter the WFI state)
@@ -331,8 +331,8 @@ static int rockchip_cpu_kill(unsigned int cpu)
  static void rockchip_cpu_die(unsigned int cpu)
  {
         v7_exit_coherency_flush(louis);
-       while (1)
-               cpu_do_idle();
+       while (1);
+               //cpu_do_idle();
  }

echo 0 > /sys/module/printk/parameters/console_suspend
echo 1 > /sys/power/pm_print_times
echo mem > sys/power/state

You can play anything
or do some test for CPU up/down:

cd /sys/devices/system/cpu/
for i in $(seq 10000); do
   echo "================= $i ============"
   for j in $(seq 100); do
     while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" 
!= "000" ]]; do

       echo 0 > cpu1/online
       echo 0 > cpu2/online
       echo 0 > cpu3/online
     done
     while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" 
!= "111" ]]; do
       echo 1 > cpu1/online
       echo 1 > cpu2/online
       echo 1 > cpu3/online
     done
   done
done
Sometimes,the system will be restart when do the about test.
I'm no sure what's happen, That maybe abnormal won't to enter the WFI 
state.

>
> -Doug
>
>
>

-- 
Thanks,
- Caesar




From wxt at rock-chips.com  Mon Jun  8 00:11:33 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon,  8 Jun 2015 15:11:33 +0800
Subject: [PATCH v5 0/3] ARM: rockchip: fix the SMP
Message-ID: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>

Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14
Tested by 176000 cycles are pass with CPU up/dowm test scripts.


Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Mon Jun  8 00:11:34 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon,  8 Jun 2015 15:11:34 +0800
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433747496-7642-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert

This is needed for stressing CPU up/down, as per:
    cd /sys/devices/system/cpu/
    for i in $(seq 10000); do
        echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducile log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
    .......
or others similar log:
    .......
    [ 4072.454453] CPU1: shutdown
    [ 4072.504436] CPU2: shutdown
    [ 4072.554426] CPU3: shutdown
    [ 4072.577827] CPU1: Booted secondary processor
    [ 4072.582611] CPU2: Booted secondary processor
    [ 4072.587426] CPU3: Booted secondary processor
    <hang>

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Doug Anderson <dianders at chromium.org>

Changes in v5:
    - back to v2 cpu on/off flow, As Heiko point out in patch v3.
    - delay more time in rockchip_boot_secondary().
    From CPU up/down tests, Needed more time to complete CPU process.
    In order to ensure a more, Here that be delayed 1ms.

Changes in v4:
    - Add reset_control_put(rstc) for the non-error case.

Changes in v3:
    - FIx the PATCH v2, it doesn't work on chromium 3.14.

Changes in v2:
    - As Heiko suggestion, re-adjust the cpu on/off flow.
    CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
    CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert

---

 arch/arm/mach-rockchip/platsmp.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..bd40852 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
 static int pmu_set_power_domain(int pd, bool on)
 {
 	u32 val = (on) ? 0 : BIT(pd);
+	struct reset_control *rstc = rockchip_get_core_reset(pd);
 	int ret;
 
 	/*
@@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
 	 * processor is powered down.
 	 */
 	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
-		struct reset_control *rstc = rockchip_get_core_reset(pd);
-
+		/* We only require the reset on the RK3288 at the moment */
 		if (IS_ERR(rstc)) {
 			pr_err("%s: could not get reset control for core %d\n",
 			       __func__, pd);
 			return PTR_ERR(rstc);
 		}
 
-		if (on)
-			reset_control_deassert(rstc);
-		else
+		if (!on)
 			reset_control_assert(rstc);
-
-		reset_control_put(rstc);
 	}
 
 	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
@@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
 		}
 	}
 
+	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
+		reset_control_deassert(rstc);
+
+	if (!IS_ERR(rstc))
+		reset_control_put(rstc);
+
 	return 0;
 }
 
@@ -148,7 +150,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * sram_base_addr + 4: 0xdeadbeaf
 		 * sram_base_addr + 8: start address for pc
 		 * */
-		udelay(10);
+		mdelay(1);
 		writel(virt_to_phys(rockchip_secondary_startup),
 			sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
-- 
1.9.1



From wxt at rock-chips.com  Mon Jun  8 00:11:35 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon,  8 Jun 2015 15:11:35 +0800
Subject: [PATCH v5 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433747496-7642-3-git-send-email-wxt@rock-chips.com>

The patch can ensure that v7_exit_coherency_flush() in rockchip_cpu_die()
executed in time.
The mdelay(1) has enough time to fix the problem of CPU offlining.
That's a workaround way in rockchip hotplug code,
At least, we haven't a better way to solve it. Who know,
that maybe fixed by chip (hardware) in the future.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

Changes in v5:
    - Fix the patch decription.
    - Add the changelog.

Changes in v4: None

Changes in v3: None

Changes in v2: None

Changes in v2:
    - As Kever points out, Fix the subject typo WFI/WFE.

---

 arch/arm/mach-rockchip/platsmp.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index bd40852..5bc2a89 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -321,6 +321,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/* ensure CPU can enter the WFI/WFE state */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Mon Jun  8 00:11:36 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon,  8 Jun 2015 15:11:36 +0800
Subject: [PATCH v5 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433747496-7642-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

Changes in v5:
    - Add the changelog.

Changes in v4: None

Changes in v3: None

Changes in v2:
    - Use the checkpatch.pl -f --subjective to check.

---

 arch/arm/mach-rockchip/platsmp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5bc2a89..e538b13 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -103,7 +103,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -133,7 +133,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -152,7 +152,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * */
 		mdelay(1);
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -331,7 +331,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -344,4 +344,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From caesar.upstream at gmail.com  Mon Jun  8 00:51:15 2015
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Mon, 08 Jun 2015 15:51:15 +0800
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
Message-ID: <55754973.6050607@gmail.com>



? 2015?06?08? 15:11, Caesar Wang ??:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
>
> In general, the correct flow is:
>
> CPU off:
>      reset_control_assert
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>      wait_for_power_domain_to_turn_off
> CPU on:
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>      wait_for_power_domain_to_turn_on
>      reset_control_deassert
>
> This is needed for stressing CPU up/down, as per:
>      cd /sys/devices/system/cpu/
>      for i in $(seq 10000); do
>          echo "================= $i ============"
>          for j in $(seq 100); do
>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
>                  echo 0 > cpu1/online
>                  echo 0 > cpu2/online
>                  echo 0 > cpu3/online
>              done
>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
>                  echo 1 > cpu1/online
>                  echo 1 > cpu2/online
>                  echo 1 > cpu3/online
>              done
>          done
>      done
>
> The following is reproducile log:
>      [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>      [34466.186824] Disabling non-boot CPUs ...
>      [34466.187509] CPU1: shutdown
>      [34466.188672] CPU2: shutdown
>      [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
>      .......
> or others similar log:
>      .......
>      [ 4072.454453] CPU1: shutdown
>      [ 4072.504436] CPU2: shutdown
>      [ 4072.554426] CPU3: shutdown
>      [ 4072.577827] CPU1: Booted secondary processor
>      [ 4072.582611] CPU2: Booted secondary processor
>      [ 4072.587426] CPU3: Booted secondary processor
>      <hang>
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Reviewed-by: Doug Anderson <dianders at chromium.org>
>
> Changes in v5:
>      - back to v2 cpu on/off flow, As Heiko point out in patch v3.
>      - delay more time in rockchip_boot_secondary().
>      From CPU up/down tests, Needed more time to complete CPU process.
>      In order to ensure a more, Here that be delayed 1ms.
>
> Changes in v4:
>      - Add reset_control_put(rstc) for the non-error case.
>
> Changes in v3:
>      - FIx the PATCH v2, it doesn't work on chromium 3.14.
>
> Changes in v2:
>      - As Heiko suggestion, re-adjust the cpu on/off flow.
>      CPU off:
>      reset_control_assert
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>      wait_for_power_domain_to_turn_off
>      CPU on:
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>      wait_for_power_domain_to_turn_on
>      reset_control_deassert

Sorry for making a mistake in here.
'Series-changes' isn't  that 'Changes in' with patman.

That's why the change log can't be 'below the cut'.

> ---
>
>   arch/arm/mach-rockchip/platsmp.c | 18 ++++++++++--------
>   1 file changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 5b4ca3c..bd40852 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>   static int pmu_set_power_domain(int pd, bool on)
>   {
>   	u32 val = (on) ? 0 : BIT(pd);
> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>   	int ret;
>   
>   	/*
> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>   	 * processor is powered down.
>   	 */
>   	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
> -
> +		/* We only require the reset on the RK3288 at the moment */
>   		if (IS_ERR(rstc)) {
>   			pr_err("%s: could not get reset control for core %d\n",
>   			       __func__, pd);
>   			return PTR_ERR(rstc);
>   		}
>   
> -		if (on)
> -			reset_control_deassert(rstc);
> -		else
> +		if (!on)
>   			reset_control_assert(rstc);
> -
> -		reset_control_put(rstc);
>   	}
>   
>   	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>   		}
>   	}
>   
> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
> +		reset_control_deassert(rstc);
> +
> +	if (!IS_ERR(rstc))
> +		reset_control_put(rstc);
> +
>   	return 0;
>   }
>   
> @@ -148,7 +150,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>   		 * sram_base_addr + 4: 0xdeadbeaf
>   		 * sram_base_addr + 8: start address for pc
>   		 * */
> -		udelay(10);
> +		mdelay(1);
>   		writel(virt_to_phys(rockchip_secondary_startup),
>   			sram_base_addr + 8);
>   		writel(0xDEADBEAF, sram_base_addr + 4);



From linux at arm.linux.org.uk  Mon Jun  8 02:24:16 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 8 Jun 2015 10:24:16 +0100
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
Message-ID: <20150608092416.GV7557@n2100.arm.linux.org.uk>

On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
> 
> In general, the correct flow is:
> 
> CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>     wait_for_power_domain_to_turn_off
> CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     wait_for_power_domain_to_turn_on
>     reset_control_deassert
> 
> This is needed for stressing CPU up/down, as per:
>     cd /sys/devices/system/cpu/
>     for i in $(seq 10000); do
>         echo "================= $i ============"
>         for j in $(seq 100); do
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
>                 echo 0 > cpu1/online
>                 echo 0 > cpu2/online
>                 echo 0 > cpu3/online
>             done
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
>                 echo 1 > cpu1/online
>                 echo 1 > cpu2/online
>                 echo 1 > cpu3/online
>             done
>         done
>     done
> 
> The following is reproducile log:

"reproducable"

>     [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>     [34466.186824] Disabling non-boot CPUs ...
>     [34466.187509] CPU1: shutdown
>     [34466.188672] CPU2: shutdown
>     [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
>     .......
> or others similar log:
>     .......
>     [ 4072.454453] CPU1: shutdown
>     [ 4072.504436] CPU2: shutdown
>     [ 4072.554426] CPU3: shutdown
>     [ 4072.577827] CPU1: Booted secondary processor
>     [ 4072.582611] CPU2: Booted secondary processor
>     [ 4072.587426] CPU3: Booted secondary processor
>     <hang>
> 
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Reviewed-by: Doug Anderson <dianders at chromium.org>
> 
> Changes in v5:
>     - back to v2 cpu on/off flow, As Heiko point out in patch v3.
>     - delay more time in rockchip_boot_secondary().
>     From CPU up/down tests, Needed more time to complete CPU process.
>     In order to ensure a more, Here that be delayed 1ms.
> 
> Changes in v4:
>     - Add reset_control_put(rstc) for the non-error case.
> 
> Changes in v3:
>     - FIx the PATCH v2, it doesn't work on chromium 3.14.
> 
> Changes in v2:
>     - As Heiko suggestion, re-adjust the cpu on/off flow.
>     CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>     wait_for_power_domain_to_turn_off
>     CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     wait_for_power_domain_to_turn_on
>     reset_control_deassert
> 
> ---
> 
>  arch/arm/mach-rockchip/platsmp.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 5b4ca3c..bd40852 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>  static int pmu_set_power_domain(int pd, bool on)
>  {
>  	u32 val = (on) ? 0 : BIT(pd);
> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>  	int ret;
>  
>  	/*
> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>  	 * processor is powered down.
>  	 */
>  	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
> -
> +		/* We only require the reset on the RK3288 at the moment */
>  		if (IS_ERR(rstc)) {
>  			pr_err("%s: could not get reset control for core %d\n",
>  			       __func__, pd);
>  			return PTR_ERR(rstc);
>  		}
>  
> -		if (on)
> -			reset_control_deassert(rstc);
> -		else
> +		if (!on)
>  			reset_control_assert(rstc);
> -
> -		reset_control_put(rstc);
>  	}
>  
>  	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>  		}
>  	}
>  
> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
> +		reset_control_deassert(rstc);
> +
> +	if (!IS_ERR(rstc))
> +		reset_control_put(rstc);
> +
>  	return 0;
>  }
>  
> @@ -148,7 +150,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>  		 * sram_base_addr + 4: 0xdeadbeaf
>  		 * sram_base_addr + 8: start address for pc
>  		 * */
> -		udelay(10);
> +		mdelay(1);

The reason for this delay needs a comment, as it's not obvious why you
would need to delay before writing to the SRAM.  Also documenting in
a comment why the delay is necessary would be good.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From linux at arm.linux.org.uk  Mon Jun  8 02:28:53 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 8 Jun 2015 10:28:53 +0100
Subject: [PATCH v5 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433747496-7642-3-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-3-git-send-email-wxt@rock-chips.com>
Message-ID: <20150608092852.GW7557@n2100.arm.linux.org.uk>

On Mon, Jun 08, 2015 at 03:11:35PM +0800, Caesar Wang wrote:
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index bd40852..5bc2a89 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -321,6 +321,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
>  #ifdef CONFIG_HOTPLUG_CPU
>  static int rockchip_cpu_kill(unsigned int cpu)
>  {
> +	/* ensure CPU can enter the WFI/WFE state */

I would like to see a better comment here, describing what the problem
is.  Maybe something like this:

	/*
	 * We need a delay here to ensure that the dying CPU can finish
	 * executing v7_coherency_exit() and reach the WFI/WFE state
	 * prior to having the power domain disabled.
	 */

Thanks.

> +	mdelay(1);
> +
>  	pmu_set_power_domain(0 + cpu, false);
>  	return 1;
>  }
> -- 
> 1.9.1
> 

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From linux at arm.linux.org.uk  Mon Jun  8 02:43:34 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 8 Jun 2015 10:43:34 +0100
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
Message-ID: <20150608094334.GX7557@n2100.arm.linux.org.uk>

On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 5b4ca3c..bd40852 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>  static int pmu_set_power_domain(int pd, bool on)
>  {
>  	u32 val = (on) ? 0 : BIT(pd);
> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>  	int ret;
>  
>  	/*
> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>  	 * processor is powered down.
>  	 */
>  	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
> -
> +		/* We only require the reset on the RK3288 at the moment */
>  		if (IS_ERR(rstc)) {
>  			pr_err("%s: could not get reset control for core %d\n",
>  			       __func__, pd);
>  			return PTR_ERR(rstc);
>  		}
>  
> -		if (on)
> -			reset_control_deassert(rstc);
> -		else
> +		if (!on)
>  			reset_control_assert(rstc);
> -
> -		reset_control_put(rstc);
>  	}

Do we need the CPU part number check for the assertion/deassertion of
the reset control?  Surely the DT provides this where appropriate and
omits it where it's inappropriate?

If so, I'd separate out the decision whether to error out from the
decision whether to assert the reset control, like this:

	if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
		pr_err("%s: could not get reset control for core %d\n",
		       __func__, pd);
		return PTR_ERR(rstc);
	}

	if (!IS_ERR(rstc) && !on)
		reset_control_assert(rstc);

or maybe:

	if (IS_ERR(rstc) && PTR_ERR(rstc) != -ENOENT) {
		pr_err("%s: could not get reset control for core %d: %d\n",
		       __func__, pd, PTR_ERR(rstc));
		return PTR_ERR(rstc);
	}

	if (!IS_ERR(rstc) && !on)
		reset_control_assert(rstc);

which lets you detect whether of_reset_control_get() failed because the
reset control was not present (and thus not required) vs failed for some
other reason - and this means that the issue of whether the reset
control is used is entirely up to the supplied DT file.

>  
>  	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>  		}
>  	}
>  
> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
> +		reset_control_deassert(rstc);
> +
> +	if (!IS_ERR(rstc))
> +		reset_control_put(rstc);
> +

and here:
	if (!IS_ERR(rstc)) {
		if (on)
			reset_control_deassert(rstc);
		reset_control_put(rstc);
	}

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From thierry.reding at gmail.com  Mon Jun  8 07:02:58 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 8 Jun 2015 16:02:58 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150605231058.GQ7557@n2100.arm.linux.org.uk>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
 <20150605231058.GQ7557@n2100.arm.linux.org.uk>
Message-ID: <20150608140256.GA10354@ulmo.nvidia.com>

On Sat, Jun 06, 2015 at 12:10:58AM +0100, Russell King - ARM Linux wrote:
> On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> > Hi Thierry
> > 
> > Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> > > If this is specific to the Rockchip implementation, shouldn't this go
> > > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > > could then simply go into the Rockchip DRM tree.
> > 
> > actually, we determined that the supply names are universal to the IP
> > (both in imx and rockchip and probably more if there are more users
> > out there). Just Russell requested that we don't pollute the generic
> > code until necessary, as it looks like the supply of those is somehow
> > handled internally on the imx.
> 
> Why do you think it's universal?
> 
> Let's start from the beginning, before we create something that's not
> representative of the hardware.
> 
> dw_hdmi actually drives two pieces of hardware - the HDMI transmitter,
> and a separate hardware block, the HDMI phy.
> 
> There are at least two possible HDMI phys referenced in the iMX
> documentation - there is one called HEAC which doesn't appear in iMX
> devices afaik, and the one which does, which is a 3D phy.

I'm not sure I understand correctly. Are these PHYs exchangeable? Does
the DesignWare IP provide them or could they be provided separately? I
see register definitions for a "source" PHY and a "master" PHY, where
the latter seems to be an I2C controller rather than a PHY. Perhaps it
is used to communicate with an external PHY?

Can somebody give me a quick summary (or point me to documentation) on
how this works?

> The 3D phy top level IO diagram does have VPH and VP power supplies,
> but it also has VP_FILT0, VP_FILT1, VP_FILT2, VP_FILT3 and GD labelled
> up as "Power supply signals".  Where they connect to in the rest of the
> system - or whether they are connected - is undocumented.
> 
> The HDMI transmitter itself is not documented what it's supplies
> actually are.
> 
> So, what we currently have in DT for dw_hdmi is something which doesn't
> _quite_ reflect the hardware right now, and to go adding VP and VPH
> supplies to the generic binding is wrong - it doesn't follow the
> hardware structure detailed in the iMX documentation I have.
> 
> As the Rockchip documentation is not available, I can't comment whether
> it would be current proposal is appropriate for Rockchip or not, which
> is why I haven't commented on this other than saying that it's not
> appropriate to be a generic dw_hdmi binding.
> 
> If we wanted to model this correctly, then for iMX, I would suggest
> that the HDMI phy should be modelled in DT, and _all_ the six VP*
> supplies are modelled - and we should assume that "GD" is a "power
> good" signal, though we don't know that for certain.

Perhaps VP_FILT* are sourced from the same supply as VP, so maybe we
don't have to care at the DT level?

> What we also don't know on iMX6 is what voltages any of these are
> supplied with.

A rather common nuisance with these licensed IP blocks is that some of
the details may be hidden in SoC glue, resulting in the interface being
different on each SoC. Given all of the above it sounds like i.MX could
have some internal glue to supply VP and VPH and there'd be no sensible
way to represent them in DT.

> So, as we don't have much certainty here, and we know that adding it
> to what is the HDMI transmitter would be wrong, I'd suggest not
> modelling it in a generic way at present.

Does DesignWare by any chance offer documentation about the IP? If not I
agree that the safest thing to do for now would be to make this Rockchip
specific. If it should prove to be generic after all (in which case i.MX
would seem to provide SoC glue to supply them) we can still promote the
supplies to be generic. They'd need to be optional to handle the i.MX,
though. Or perhaps a dummy regulator could be referenced, representing
the SoC-internal supply to the block. Maybe there even is a (SoC-
specific) way to control this internal regulator?

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150608/a9533e31/attachment.sig>

From linux at arm.linux.org.uk  Mon Jun  8 07:29:26 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 8 Jun 2015 15:29:26 +0100
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150608140256.GA10354@ulmo.nvidia.com>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
 <20150605231058.GQ7557@n2100.arm.linux.org.uk>
 <20150608140256.GA10354@ulmo.nvidia.com>
Message-ID: <20150608142926.GY7557@n2100.arm.linux.org.uk>

On Mon, Jun 08, 2015 at 04:02:58PM +0200, Thierry Reding wrote:
> On Sat, Jun 06, 2015 at 12:10:58AM +0100, Russell King - ARM Linux wrote:
> > On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> > > Hi Thierry
> > > 
> > > Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> > > > If this is specific to the Rockchip implementation, shouldn't this go
> > > > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > > > could then simply go into the Rockchip DRM tree.
> > > 
> > > actually, we determined that the supply names are universal to the IP
> > > (both in imx and rockchip and probably more if there are more users
> > > out there). Just Russell requested that we don't pollute the generic
> > > code until necessary, as it looks like the supply of those is somehow
> > > handled internally on the imx.
> > 
> > Why do you think it's universal?
> > 
> > Let's start from the beginning, before we create something that's not
> > representative of the hardware.
> > 
> > dw_hdmi actually drives two pieces of hardware - the HDMI transmitter,
> > and a separate hardware block, the HDMI phy.
> > 
> > There are at least two possible HDMI phys referenced in the iMX
> > documentation - there is one called HEAC which doesn't appear in iMX
> > devices afaik, and the one which does, which is a 3D phy.
> 
> I'm not sure I understand correctly. Are these PHYs exchangeable? Does
> the DesignWare IP provide them or could they be provided separately?

You're asking questions we have no real answers to - all we have is the
available documentation provided by Freescale - we don't even have the
Rochchip documentation.

>From the Freescale documentation, which documents the HDMI transmitter
entirely separately from the HDMI phy, I would say that the IP is
structured as two entirely separate blocks, and the chip designer is
free to choose an appropriate phy from a range of HDMI phys.

Moreover, in the feature list for the HDMI transmitter, it says (though
this is not applicable to iMX6 - and is probably lifted from the
Synopsis documentation):

"* Option to remove pixel repetition clock from HDMI TX interface for an
  easy integration with third party HDMI TX PHYs"

So - here's the question: what do we do when we find something using the
Synopsis design-ware HDMI transmitter with a different HDMI phy?

Remember, VP, VPH, VP_FILT_* are all part of the HDMI phy according to
the freescale documentation, and not part of the HDMI transmitter.

> I
> see register definitions for a "source" PHY and a "master" PHY, where
> the latter seems to be an I2C controller rather than a PHY. Perhaps it
> is used to communicate with an external PHY?

I'm not sure where you get that from.  Maybe you could give a chapter
reference?

Looking deeper at this HEAC issue, that is a separate, smaller phy which
doesn't have much to do with video - though it remains rather undocumented
in the freescale docs.  That's only going on a block diagram near the
start of the HDMI transmitter chapter though.

> > If we wanted to model this correctly, then for iMX, I would suggest
> > that the HDMI phy should be modelled in DT, and _all_ the six VP*
> > supplies are modelled - and we should assume that "GD" is a "power
> > good" signal, though we don't know that for certain.
> 
> Perhaps VP_FILT* are sourced from the same supply as VP, so maybe we
> don't have to care at the DT level?

We'd be guessing - and that's exactly my point.  Designing something at
DT level based on guesswork is no way to go, especially with a generic
bit of IP which would be re-used across multiple different platforms.

> > What we also don't know on iMX6 is what voltages any of these are
> > supplied with.
> 
> A rather common nuisance with these licensed IP blocks is that some of
> the details may be hidden in SoC glue, resulting in the interface being
> different on each SoC. Given all of the above it sounds like i.MX could
> have some internal glue to supply VP and VPH and there'd be no sensible
> way to represent them in DT.

... or it's entirely possible that all these supplies are always fed by
the iMX6 SoC all the time.

> > So, as we don't have much certainty here, and we know that adding it
> > to what is the HDMI transmitter would be wrong, I'd suggest not
> > modelling it in a generic way at present.
> 
> Does DesignWare by any chance offer documentation about the IP? If not I
> agree that the safest thing to do for now would be to make this Rockchip
> specific.

That's _exactly_ why I raised the point originally, and said that it should
be Rockchip specific until we know better.  Glad you've caught up with my
thinking. :)

However, my thinking _now_ is that it shouldn't even be modelled as part
of our HDMI transmitter DT blob, but we should be modelling the HDMI
transmitter separately from the HDMI phy as two separate DT blobs, and
then the HDMI phy blob gets the (possibly optional) VPH and VP supplies.

What if someone designs a chip with their own HDMI phy which uses
different supplies?

This is one of the problems I have with DT - DT needs us to describe
the hardware correctly first time around, when we may not have all the
available facts to make proper decisions, and wrong decisions can very
well lead to serious headaches later on because we didn't model
something correctly - and we're stuck with the wrong decisions for ever.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From thierry.reding at gmail.com  Mon Jun  8 07:49:09 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 8 Jun 2015 16:49:09 +0200
Subject: [PATCH v4 2/3] drm/rockchip: implement dw_hdmi supplies for the
 Rockchip implementation
In-Reply-To: <17068264.uLYIadrGJJ@diego>
References: <1707049.JEvfTcofKv@diego>
 <17068264.uLYIadrGJJ@diego>
Message-ID: <20150608144858.GF10354@ulmo.nvidia.com>

On Fri, Jun 05, 2015 at 07:06:38PM +0200, Heiko St?bner wrote:
> The Rockchip implementation of the IP exposes the supplies outside and
> expects them to be supplied by a pmic. So implement regulator handling
> for them.
> 
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> Acked-by: Philipp Zabel <p.zabel at pengutronix.de>
> ---
> changes since v3:
> - split generic dt-bindings and rockchip implementation
> - add Ack from Philipp Zabel
> changes since v2:
> - rename supplies to the names found in the hdmi IP databook
> changes since v1:
> - follow suggestion from Russell King to keep regulator handling local
>   to the rockchip implementation for the time being and only generalize
>   when a real second implementation needs regulator handling
> 
>  drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 32 ++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> index 80d6fc8..9c003fa 100644
> --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
> @@ -11,6 +11,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/mfd/syscon.h>
>  #include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
>  #include <drm/drm_of.h>
>  #include <drm/drmP.h>
>  #include <drm/drm_crtc_helper.h>
> @@ -28,6 +29,9 @@ struct rockchip_hdmi {
>  	struct device *dev;
>  	struct regmap *regmap;
>  	struct drm_encoder encoder;
> +	struct regulator_bulk_data supplies[2];
> +	int nsupplies;

unsigned int, please. Also I personally prefer the num_ prefix and it's
slightly more common in DRM code (even in the Rockchip driver).

> +	bool supplies_enabled;
>  };
>  
>  #define to_rockchip_hdmi(x)	container_of(x, struct rockchip_hdmi, x)
> @@ -179,6 +183,12 @@ static struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
>  
>  static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
>  {
> +	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
> +
> +	if (hdmi->nsupplies > 0 && hdmi->supplies_enabled) {
> +		regulator_bulk_disable(hdmi->nsupplies, hdmi->supplies);
> +		hdmi->supplies_enabled = false;
> +	}
>  }
>  
>  static bool
> @@ -199,7 +209,16 @@ static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
>  {
>  	struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
>  	u32 val;
> -	int mux;
> +	int mux, ret;
> +
> +	if (hdmi->nsupplies > 0 && !hdmi->supplies_enabled) {
> +		ret = regulator_bulk_enable(hdmi->nsupplies, hdmi->supplies);
> +		if (ret) {
> +			dev_err(hdmi->dev, "could not enable hdmi analog supplies\n");

"HDMI" please. And perhaps you want to add the error code to the message
as well?

> +			return;
> +		}
> +		hdmi->supplies_enabled = true;
> +	}
>  
>  	mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
>  	if (mux)
> @@ -275,6 +294,17 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
>  	if (!iores)
>  		return -ENXIO;
>  
> +	hdmi->supplies[0].supply = "vp";
> +	hdmi->supplies[1].supply = "vph";
> +	hdmi->nsupplies = 2;
> +
> +	ret = devm_regulator_bulk_get(hdmi->dev,
> +				      hdmi->nsupplies, hdmi->supplies);

I think it'd be slightly more idiomatic to put hdmi->nsupplies on the
first line.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150608/8280d80d/attachment.sig>

From thierry.reding at gmail.com  Mon Jun  8 08:44:53 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Mon, 8 Jun 2015 17:44:53 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150608142926.GY7557@n2100.arm.linux.org.uk>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
 <20150605231058.GQ7557@n2100.arm.linux.org.uk>
 <20150608140256.GA10354@ulmo.nvidia.com>
 <20150608142926.GY7557@n2100.arm.linux.org.uk>
Message-ID: <20150608154448.GA11103@ulmo.nvidia.com>

On Mon, Jun 08, 2015 at 03:29:26PM +0100, Russell King - ARM Linux wrote:
> On Mon, Jun 08, 2015 at 04:02:58PM +0200, Thierry Reding wrote:
> > On Sat, Jun 06, 2015 at 12:10:58AM +0100, Russell King - ARM Linux wrote:
> > > On Fri, Jun 05, 2015 at 02:16:40PM +0200, Heiko St?bner wrote:
> > > > Hi Thierry
> > > > 
> > > > Am Freitag, 5. Juni 2015, 13:02:01 schrieb Thierry Reding:
> > > > > If this is specific to the Rockchip implementation, shouldn't this go
> > > > > into Documentation/devicetree/bindings/video/dw_hdmi-rockchip.txt? It
> > > > > could then simply go into the Rockchip DRM tree.
> > > > 
> > > > actually, we determined that the supply names are universal to the IP
> > > > (both in imx and rockchip and probably more if there are more users
> > > > out there). Just Russell requested that we don't pollute the generic
> > > > code until necessary, as it looks like the supply of those is somehow
> > > > handled internally on the imx.
> > > 
> > > Why do you think it's universal?
> > > 
> > > Let's start from the beginning, before we create something that's not
> > > representative of the hardware.
> > > 
> > > dw_hdmi actually drives two pieces of hardware - the HDMI transmitter,
> > > and a separate hardware block, the HDMI phy.
> > > 
> > > There are at least two possible HDMI phys referenced in the iMX
> > > documentation - there is one called HEAC which doesn't appear in iMX
> > > devices afaik, and the one which does, which is a 3D phy.
> > 
> > I'm not sure I understand correctly. Are these PHYs exchangeable? Does
> > the DesignWare IP provide them or could they be provided separately?
> 
> You're asking questions we have no real answers to - all we have is the
> available documentation provided by Freescale - we don't even have the
> Rochchip documentation.
> 
> From the Freescale documentation, which documents the HDMI transmitter
> entirely separately from the HDMI phy, I would say that the IP is
> structured as two entirely separate blocks, and the chip designer is
> free to choose an appropriate phy from a range of HDMI phys.

Does it associate any of the registers with the HDMI PHY? According to
the register definitions in drivers/gpu/drm/bridge/dw_hdmi.h the PHY
registers are interleaved with other registers that are likely part of
the HDMI transmitter proper (there are things like HDCP and CEC engines
in that IP as well).

> Moreover, in the feature list for the HDMI transmitter, it says (though
> this is not applicable to iMX6 - and is probably lifted from the
> Synopsis documentation):
> 
> "* Option to remove pixel repetition clock from HDMI TX interface for an
>   easy integration with third party HDMI TX PHYs"
> 
> So - here's the question: what do we do when we find something using the
> Synopsis design-ware HDMI transmitter with a different HDMI phy?
> 
> Remember, VP, VPH, VP_FILT_* are all part of the HDMI phy according to
> the freescale documentation, and not part of the HDMI transmitter.
> 
> > I
> > see register definitions for a "source" PHY and a "master" PHY, where
> > the latter seems to be an I2C controller rather than a PHY. Perhaps it
> > is used to communicate with an external PHY?
> 
> I'm not sure where you get that from.  Maybe you could give a chapter
> reference?

That's just from skimming drivers/gpu/drm/bridge/dw_hdmi.h (register
offsets 0x3000 and the following). The large gap between them and the
preceding FC registers could be an additional indication that they are
indeed separate IP blocks. Then again, the AUD registers start at an
offset of 0x3100, so maybe it's no indication at all.

Are these the registers used to control the PHY that you're referring
to? It seems odd to me that the documentation would specify these
registers interleaved with other registers if the PHYs can be freely
chosen from a set of HDMI PHYs. Perhaps the set of PHYs that can be used
need to expose the same integration interface? Maybe these registers
aren't used to control the PHY at all but rather configure the interface
between transmitter and PHY?

Sorry if these are more questions that the documentation doesn't answer.
Just trying to understand what's going on.

> Looking deeper at this HEAC issue, that is a separate, smaller phy which
> doesn't have much to do with video - though it remains rather undocumented
> in the freescale docs.  That's only going on a block diagram near the
> start of the HDMI transmitter chapter though.

HEAC could be "HDMI Ethernet Audio Control", see here:

	http://en.wikipedia.org/wiki/HDMI#ARC
	http://en.wikipedia.org/wiki/HDMI#HEC

> > > If we wanted to model this correctly, then for iMX, I would suggest
> > > that the HDMI phy should be modelled in DT, and _all_ the six VP*
> > > supplies are modelled - and we should assume that "GD" is a "power
> > > good" signal, though we don't know that for certain.
> > 
> > Perhaps VP_FILT* are sourced from the same supply as VP, so maybe we
> > don't have to care at the DT level?
> 
> We'd be guessing - and that's exactly my point.  Designing something at
> DT level based on guesswork is no way to go, especially with a generic
> bit of IP which would be re-used across multiple different platforms.

Agreed.

> > > What we also don't know on iMX6 is what voltages any of these are
> > > supplied with.
> > 
> > A rather common nuisance with these licensed IP blocks is that some of
> > the details may be hidden in SoC glue, resulting in the interface being
> > different on each SoC. Given all of the above it sounds like i.MX could
> > have some internal glue to supply VP and VPH and there'd be no sensible
> > way to represent them in DT.
> 
> ... or it's entirely possible that all these supplies are always fed by
> the iMX6 SoC all the time.

Yes, that's what I was implying.

> > > So, as we don't have much certainty here, and we know that adding it
> > > to what is the HDMI transmitter would be wrong, I'd suggest not
> > > modelling it in a generic way at present.
> > 
> > Does DesignWare by any chance offer documentation about the IP? If not I
> > agree that the safest thing to do for now would be to make this Rockchip
> > specific.
> 
> That's _exactly_ why I raised the point originally, and said that it should
> be Rockchip specific until we know better.  Glad you've caught up with my
> thinking. :)
> 
> However, my thinking _now_ is that it shouldn't even be modelled as part
> of our HDMI transmitter DT blob, but we should be modelling the HDMI
> transmitter separately from the HDMI phy as two separate DT blobs, and
> then the HDMI phy blob gets the (possibly optional) VPH and VP supplies.

Yes, I agree. One problem that you could run into with such a split is
that the PHY control registers may be interleaved with the registers of
the HDMI transmitter. But perhaps my understanding is wrong and the PHY
is truly controlled via a completely own set of registers. Looking at
the implementation, the HDMI_PHY_* registers seem to be used to control
various aspects of an interface between transmitter and PHY rather than
the PHY itself and it seems like the PHY itself is really an I2C slave
accessed using the I2C master controlled using the HDMI_PHY_I2CM_*
registers.

So perhaps the HDMI transmitter DT node really should expose the PHY as
an I2C child. In fact, looking at HDMI_PHY_I2CM_SLAVE_ADDR_* field
values (lines 870 and 871 in dw_hdmi.h) it should have two children, one
for the "GEN2" PHY and one for the "HEAC" PHY. You could even go as far
as exposing the HDMI_PHY_I2CM_* registers as I2C master and implement
the PHYs as proper I2C client drivers, but that might be overkill,
especially considering that you'd need to have extra API to convey the
HDMI configuration. Still, might be worth considering to make the split
really explicit.

I guess I've answered most of my earlier questions myself...

> What if someone designs a chip with their own HDMI phy which uses
> different supplies?

That's really one more reason to write proper drivers for the PHYs. If
you really ever have to deal with a different PHY chances are that more
than just the supplies will be different, in which case you'd need to
somehow also abstract away the interoperation between HDMI transmitter
and PHY.

> This is one of the problems I have with DT - DT needs us to describe
> the hardware correctly first time around, when we may not have all the
> available facts to make proper decisions, and wrong decisions can very
> well lead to serious headaches later on because we didn't model
> something correctly - and we're stuck with the wrong decisions for ever.

I feel the same way. Although there have been occasional exceptions to
the DT ABI stability rule if it could be proven that an existing binding
was completely wrong, I've made the experience that putting as little as
possible into DT (and at the same time resist the temptation of a
generic solution) helps keep the headaches in check.

Fortunately the dw-hdmi driver gets much of this right already (it's
helper code rather than a proper driver), so keeping things like power
supplies specific to a particular integration should be easy to do and
prevent potential future incompatibilities.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150608/649817de/attachment.sig>

From linux at arm.linux.org.uk  Mon Jun  8 09:34:21 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 8 Jun 2015 17:34:21 +0100
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150608154448.GA11103@ulmo.nvidia.com>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
 <20150605231058.GQ7557@n2100.arm.linux.org.uk>
 <20150608140256.GA10354@ulmo.nvidia.com>
 <20150608142926.GY7557@n2100.arm.linux.org.uk>
 <20150608154448.GA11103@ulmo.nvidia.com>
Message-ID: <20150608163420.GZ7557@n2100.arm.linux.org.uk>

On Mon, Jun 08, 2015 at 05:44:53PM +0200, Thierry Reding wrote:
> On Mon, Jun 08, 2015 at 03:29:26PM +0100, Russell King - ARM Linux wrote:
> > You're asking questions we have no real answers to - all we have is the
> > available documentation provided by Freescale - we don't even have the
> > Rochchip documentation.
> > 
> > From the Freescale documentation, which documents the HDMI transmitter
> > entirely separately from the HDMI phy, I would say that the IP is
> > structured as two entirely separate blocks, and the chip designer is
> > free to choose an appropriate phy from a range of HDMI phys.
> 
> Does it associate any of the registers with the HDMI PHY? According to
> the register definitions in drivers/gpu/drm/bridge/dw_hdmi.h the PHY
> registers are interleaved with other registers that are likely part of
> the HDMI transmitter proper (there are things like HDCP and CEC engines
> in that IP as well).

The protocol stuff is handled by the HDMI Tx - the phy is the conversion
from the internal digital to the interface domain.

I could write lots to describe it, but really, the best thing to do is
to download the iMX6 documentation and take a peek at it...

https://community.freescale.com/docs/DOC-101840

Particularly, look at the HDMI 3D Phy section, the system level block
diagram (34.1.5.1), and 34.2.1 which has the top level I/O diagram for
just the 3D phy.

The previous section (section 33) covers the HDMI Tx.

> > Moreover, in the feature list for the HDMI transmitter, it says (though
> > this is not applicable to iMX6 - and is probably lifted from the
> > Synopsis documentation):
> > 
> > "* Option to remove pixel repetition clock from HDMI TX interface for an
> >   easy integration with third party HDMI TX PHYs"
> > 
> > So - here's the question: what do we do when we find something using the
> > Synopsis design-ware HDMI transmitter with a different HDMI phy?
> > 
> > Remember, VP, VPH, VP_FILT_* are all part of the HDMI phy according to
> > the freescale documentation, and not part of the HDMI transmitter.
> > 
> > > I
> > > see register definitions for a "source" PHY and a "master" PHY, where
> > > the latter seems to be an I2C controller rather than a PHY. Perhaps it
> > > is used to communicate with an external PHY?
> > 
> > I'm not sure where you get that from.  Maybe you could give a chapter
> > reference?
> 
> That's just from skimming drivers/gpu/drm/bridge/dw_hdmi.h (register
> offsets 0x3000 and the following). The large gap between them and the
> preceding FC registers could be an additional indication that they are
> indeed separate IP blocks. Then again, the AUD registers start at an
> offset of 0x3100, so maybe it's no indication at all.

Ah, you're getting slightly confused.

All those registers are to do with the HDMI Tx itself.  The block at
0x3000 to 0x3007 is to do with the HDMI Tx receiving various status
signals from the HDMI Phy, such as HPD, rxsense, and whether the phy
PLL is locked (which I'm fairly certain is mis-described, as there is
no output signal from the phy to indicate this, but there is a TX_READY
signal.)

The set at 0x3020-0x3032 are to do with talking to the HDMI phy over
the dedicated I2C interface integrated into the HDMI Tx.  All the
HDMI Phy registers are accessed through this I2C interface.

> > What if someone designs a chip with their own HDMI phy which uses
> > different supplies?
> 
> That's really one more reason to write proper drivers for the PHYs. If
> you really ever have to deal with a different PHY chances are that more
> than just the supplies will be different, in which case you'd need to
> somehow also abstract away the interoperation between HDMI transmitter
> and PHY.

Exactly, but that didn't happen before this code moved out of
drivers/staging, which is rather unfortunate, but everyone was too busy
to put much thought into that.

This is one of the problems when drivers are taken from BSPs rather than
going away and writing something from documentation: if you start afresh,
you can model the code according to the documentation without any of the
original BSP decisions in place.  If you start from the BSP code, you
have a whole pile of changes you need to identify, and it's very easy to
overlook something, because what you have works.

It's something which _should_ be done nevertheless.  The problem is
finding someone with the time and motivation to do a good job.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From dianders at chromium.org  Mon Jun  8 13:52:15 2015
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 8 Jun 2015 13:52:15 -0700
Subject: [PATCH v3 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <55752067.2040108@rock-chips.com>
References: <1433517104-7595-1-git-send-email-wxt@rock-chips.com>
 <1433517104-7595-3-git-send-email-wxt@rock-chips.com>
 <CAD=FV=UMkFtOFYpY+MUZOegnmFLdW3ZgNivwdHChv0MLr50sVQ@mail.gmail.com>
 <20150605182947.GN7557@n2100.arm.linux.org.uk>
 <CAD=FV=UamkH+RHmHHVzGKZda_w0teGBdfcH-LbCKqyp2q1OVqA@mail.gmail.com>
 <55752067.2040108@rock-chips.com>
Message-ID: <CAD=FV=W3Ot0vymVguuE5YwENjmFVaFOxXoNODdu7UwzErGxTxA@mail.gmail.com>

Caesar,

On Sun, Jun 7, 2015 at 9:56 PM, Caesar Wang <wxt at rock-chips.com> wrote:
> OK.
> The dying processor to execute v7_exit_coherency_flush(),not that the dying
> processor to be in WFI/WFE.
>
> It's needed to enter WFI/WFE state from the ARM refer document when CPU
> down.
>
> But......
>
> Here is my test: (won't to enter the WFI state)
> @@ -331,8 +331,8 @@ static int rockchip_cpu_kill(unsigned int cpu)
>  static void rockchip_cpu_die(unsigned int cpu)
>  {
>         v7_exit_coherency_flush(louis);
> -       while (1)
> -               cpu_do_idle();
> +       while (1);
> +               //cpu_do_idle();
>  }
>
> echo 0 > /sys/module/printk/parameters/console_suspend
> echo 1 > /sys/power/pm_print_times
> echo mem > sys/power/state
>
> You can play anything
> or do some test for CPU up/down:
>
> cd /sys/devices/system/cpu/
> for i in $(seq 10000); do
>   echo "================= $i ============"
>   for j in $(seq 100); do
>     while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" !=
> "000" ]]; do
>
>       echo 0 > cpu1/online
>       echo 0 > cpu2/online
>       echo 0 > cpu3/online
>     done
>     while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" !=
> "111" ]]; do
>       echo 1 > cpu1/online
>       echo 1 > cpu2/online
>       echo 1 > cpu3/online
>     done
>   done
> done
> Sometimes,the system will be restart when do the about test.

I assume you meant the _above_ test.  So it sometimes works and
sometimes doesn't?  Strange...

> I'm no sure what's happen, That maybe abnormal won't to enter the WFI state.

Good test.  I think I understood what you said above: basically if you
don't get to the WFI state then the system will sometimes restart.

I guess that seems a little strange to me since I would have thought
that since you assert "reset" to the CPU before you power it off it
wouldn't matter a whole lot what state the system was in.  The
processor has exited concurrency and isn't touching any memory, so
nothing it does should be hurting anyone.  ...but I also am only
guessing about how all this works / trying to use common sense.  If we
really need to be in WFI/WFE then I guess that's what we need to do.

It still makes me nervous to say both that we "need to be in WFI" and
that we have a loop around cpu_do_idle().  The loop implies that
cpu_do_idle() might return sometimes.  That would be OK, except now
we've learned that if we happen to kill the CPU while we're executing
the loop that it might crash the system.  That's pretty non-ideal.  I
know the chances are incredibly unlikely, but still something that
worries me...


-Doug


From caesar.wang at rock-chips.com  Mon Jun  8 14:54:23 2015
From: caesar.wang at rock-chips.com (Caesar Wang)
Date: Tue, 09 Jun 2015 05:54:23 +0800
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <20150608092416.GV7557@n2100.arm.linux.org.uk>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
 <20150608092416.GV7557@n2100.arm.linux.org.uk>
Message-ID: <55760F0F.9010302@rock-chips.com>



? 2015?06?08? 17:24, Russell King - ARM Linux ??:
> On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
>> We need different orderings when turning a core on and turning a core
>> off.  In one case we need to assert reset before turning power off.
>> In ther other case we need to turn power on and the deassert reset.
>>
>> In general, the correct flow is:
>>
>> CPU off:
>>      reset_control_assert
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>>      wait_for_power_domain_to_turn_off
>> CPU on:
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>>      wait_for_power_domain_to_turn_on
>>      reset_control_deassert
>>
>> This is needed for stressing CPU up/down, as per:
>>      cd /sys/devices/system/cpu/
>>      for i in $(seq 10000); do
>>          echo "================= $i ============"
>>          for j in $(seq 100); do
>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
>>                  echo 0 > cpu1/online
>>                  echo 0 > cpu2/online
>>                  echo 0 > cpu3/online
>>              done
>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
>>                  echo 1 > cpu1/online
>>                  echo 1 > cpu2/online
>>                  echo 1 > cpu3/online
>>              done
>>          done
>>      done
>>
>> The following is reproducile log:
> "reproducable"
>
>>      [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>>      [34466.186824] Disabling non-boot CPUs ...
>>      [34466.187509] CPU1: shutdown
>>      [34466.188672] CPU2: shutdown
>>      [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
>>      .......
>> or others similar log:
>>      .......
>>      [ 4072.454453] CPU1: shutdown
>>      [ 4072.504436] CPU2: shutdown
>>      [ 4072.554426] CPU3: shutdown
>>      [ 4072.577827] CPU1: Booted secondary processor
>>      [ 4072.582611] CPU2: Booted secondary processor
>>      [ 4072.587426] CPU3: Booted secondary processor
>>      <hang>
>>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> Reviewed-by: Doug Anderson <dianders at chromium.org>
>>
>> Changes in v5:
>>      - back to v2 cpu on/off flow, As Heiko point out in patch v3.
>>      - delay more time in rockchip_boot_secondary().
>>      From CPU up/down tests, Needed more time to complete CPU process.
>>      In order to ensure a more, Here that be delayed 1ms.
>>
>> Changes in v4:
>>      - Add reset_control_put(rstc) for the non-error case.
>>
>> Changes in v3:
>>      - FIx the PATCH v2, it doesn't work on chromium 3.14.
>>
>> Changes in v2:
>>      - As Heiko suggestion, re-adjust the cpu on/off flow.
>>      CPU off:
>>      reset_control_assert
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>>      wait_for_power_domain_to_turn_off
>>      CPU on:
>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>>      wait_for_power_domain_to_turn_on
>>      reset_control_deassert
>>
>> ---
>>
>>   arch/arm/mach-rockchip/platsmp.c | 18 ++++++++++--------
>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>
>> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
>> index 5b4ca3c..bd40852 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>>   static int pmu_set_power_domain(int pd, bool on)
>>   {
>>   	u32 val = (on) ? 0 : BIT(pd);
>> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>>   	int ret;
>>   
>>   	/*
>> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>>   	 * processor is powered down.
>>   	 */
>>   	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
>> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
>> -
>> +		/* We only require the reset on the RK3288 at the moment */
>>   		if (IS_ERR(rstc)) {
>>   			pr_err("%s: could not get reset control for core %d\n",
>>   			       __func__, pd);
>>   			return PTR_ERR(rstc);
>>   		}
>>   
>> -		if (on)
>> -			reset_control_deassert(rstc);
>> -		else
>> +		if (!on)
>>   			reset_control_assert(rstc);
>> -
>> -		reset_control_put(rstc);
>>   	}
>>   
>>   	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>>   		}
>>   	}
>>   
>> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
>> +		reset_control_deassert(rstc);
>> +
>> +	if (!IS_ERR(rstc))
>> +		reset_control_put(rstc);
>> +
>>   	return 0;
>>   }
>>   
>> @@ -148,7 +150,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>>   		 * sram_base_addr + 4: 0xdeadbeaf
>>   		 * sram_base_addr + 8: start address for pc
>>   		 * */
>> -		udelay(10);
>> +		mdelay(1);
> The reason for this delay needs a comment, as it's not obvious why you
> would need to delay before writing to the SRAM.  Also documenting in
> a comment why the delay is necessary would be good.
>

Sorry for delay, I wait a better solution for this.
We don't need any 10us delay or 1m delay, I think.

-		udelay(10);

+        while (readl(sram_base_addr + 4 ) != 1); //lock =1


We need do that if i'm correct from the bootrom code.
Tested are pass over 120000 cycles on today, I will wait more testing 
cycles to confirm that's ok.



-- 
**************************************************************************************
???    Caesar Wang
Product R&D Dept.III
Fuzhou Rockchip Electronics Co.Ltd
Addr?  NO.18 Building, A District, Fuzhou Software Park,Gulou District,Fuzhou, Fujian,China(Fuzhou Headquarters)
               21F,Malata Building,Kejizhongyi Avenue,Nanshan District,Shenzhen  (Shenzhen Office)
Tel?+86-591-83991906/07 - 8221
Mobile:+86 15059456742
E-mail : wxt at rock-chips.com
***************************************************************************************
***************************************************************************************
IMPORTANT NOTICE: This email is from Fuzhou Rockchip Electronics Co., Ltd .The contents of this email and any attachments may
contain information that is privileged, confidential and/or exempt from disclosure under applicable law and relevant NDA.
If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the
information is STRICTLY PROHIBITED. Please immediately contact the sender as soon as possible and destroy the material
in its entirety in any format. Thank you.
***************************************************************************************




From wxt at rock-chips.com  Mon Jun  8 17:40:12 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 09 Jun 2015 08:40:12 +0800
Subject: [PATCH v5 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <20150608092852.GW7557@n2100.arm.linux.org.uk>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-3-git-send-email-wxt@rock-chips.com>
 <20150608092852.GW7557@n2100.arm.linux.org.uk>
Message-ID: <557635EC.7040402@rock-chips.com>



? 2015?06?08? 17:28, Russell King - ARM Linux ??:
> On Mon, Jun 08, 2015 at 03:11:35PM +0800, Caesar Wang wrote:
>> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
>> index bd40852..5bc2a89 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -321,6 +321,9 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
>>   #ifdef CONFIG_HOTPLUG_CPU
>>   static int rockchip_cpu_kill(unsigned int cpu)
>>   {
>> +	/* ensure CPU can enter the WFI/WFE state */
> I would like to see a better comment here, describing what the problem
> is.  Maybe something like this:
>
> 	/*
> 	 * We need a delay here to ensure that the dying CPU can finish
> 	 * executing v7_coherency_exit() and reach the WFI/WFE state
> 	 * prior to having the power domain disabled.
> 	 */
>
> Thanks.

OK,
Thanks!
>> +	mdelay(1);
>> +
>>   	pmu_set_power_domain(0 + cpu, false);
>>   	return 1;
>>   }
>> -- 
>> 1.9.1
>>

-- 
Thanks,
- Caesar




From wxt at rock-chips.com  Mon Jun  8 17:43:56 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 09 Jun 2015 08:43:56 +0800
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <20150608094334.GX7557@n2100.arm.linux.org.uk>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
 <20150608094334.GX7557@n2100.arm.linux.org.uk>
Message-ID: <557636CC.6010809@rock-chips.com>



? 2015?06?08? 17:43, Russell King - ARM Linux ??:
> On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
>> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
>> index 5b4ca3c..bd40852 100644
>> --- a/arch/arm/mach-rockchip/platsmp.c
>> +++ b/arch/arm/mach-rockchip/platsmp.c
>> @@ -72,6 +72,7 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>>   static int pmu_set_power_domain(int pd, bool on)
>>   {
>>   	u32 val = (on) ? 0 : BIT(pd);
>> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>>   	int ret;
>>   
>>   	/*
>> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>>   	 * processor is powered down.
>>   	 */
>>   	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
>> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
>> -
>> +		/* We only require the reset on the RK3288 at the moment */
>>   		if (IS_ERR(rstc)) {
>>   			pr_err("%s: could not get reset control for core %d\n",
>>   			       __func__, pd);
>>   			return PTR_ERR(rstc);
>>   		}
>>   
>> -		if (on)
>> -			reset_control_deassert(rstc);
>> -		else
>> +		if (!on)
>>   			reset_control_assert(rstc);
>> -
>> -		reset_control_put(rstc);
>>   	}
> Do we need the CPU part number check for the assertion/deassertion of
> the reset control?  Surely the DT provides this where appropriate and
> omits it where it's inappropriate?
>
> If so, I'd separate out the decision whether to error out from the
> decision whether to assert the reset control, like this:
>
> 	if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> 		pr_err("%s: could not get reset control for core %d\n",
> 		       __func__, pd);
> 		return PTR_ERR(rstc);
> 	}
>
> 	if (!IS_ERR(rstc) && !on)
> 		reset_control_assert(rstc);
>
> or maybe:
>
> 	if (IS_ERR(rstc) && PTR_ERR(rstc) != -ENOENT) {
> 		pr_err("%s: could not get reset control for core %d: %d\n",
> 		       __func__, pd, PTR_ERR(rstc));
> 		return PTR_ERR(rstc);
> 	}
>
> 	if (!IS_ERR(rstc) && !on)
> 		reset_control_assert(rstc);
>
> which lets you detect whether of_reset_control_get() failed because the
> reset control was not present (and thus not required) vs failed for some
> other reason - and this means that the issue of whether the reset
> control is used is entirely up to the supplied DT file.
Sound resonable for me.

I hope get the Heiko and Kever option.
After all the code is uploaded by Heiko and Kever.

>>   
>>   	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>>   		}
>>   	}
>>   
>> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
>> +		reset_control_deassert(rstc);
>> +
>> +	if (!IS_ERR(rstc))
>> +		reset_control_put(rstc);
>> +
> and here:
> 	if (!IS_ERR(rstc)) {
> 		if (on)
> 			reset_control_deassert(rstc);
> 		reset_control_put(rstc);
> 	}
Ditto.


-- 
Thanks,
- Caesar




From heiko at sntech.de  Tue Jun  9 00:46:47 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 09 Jun 2015 09:46:47 +0200
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <557636CC.6010809@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <20150608094334.GX7557@n2100.arm.linux.org.uk>
 <557636CC.6010809@rock-chips.com>
Message-ID: <9253141.D1erkaHIPa@diego>

Am Dienstag, 9. Juni 2015, 08:43:56 schrieb Caesar Wang:
> ? 2015?06?08? 17:43, Russell King - ARM Linux ??:
> > On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
> >> diff --git a/arch/arm/mach-rockchip/platsmp.c
> >> b/arch/arm/mach-rockchip/platsmp.c index 5b4ca3c..bd40852 100644
> >> --- a/arch/arm/mach-rockchip/platsmp.c
> >> +++ b/arch/arm/mach-rockchip/platsmp.c
> >> @@ -72,6 +72,7 @@ static struct reset_control
> >> *rockchip_get_core_reset(int cpu)>> 
> >>   static int pmu_set_power_domain(int pd, bool on)
> >>   {
> >>   
> >>   	u32 val = (on) ? 0 : BIT(pd);
> >> 
> >> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
> >> 
> >>   	int ret;
> >>   	
> >>   	/*
> >> 
> >> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
> >> 
> >>   	 * processor is powered down.
> >>   	 */
> >>   	
> >>   	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> >> 
> >> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
> >> -
> >> +		/* We only require the reset on the RK3288 at the moment */
> >> 
> >>   		if (IS_ERR(rstc)) {
> >>   		
> >>   			pr_err("%s: could not get reset control for core %d\n",
> >>   			
> >>   			       __func__, pd);
> >>   			
> >>   			return PTR_ERR(rstc);
> >>   		
> >>   		}
> >> 
> >> -		if (on)
> >> -			reset_control_deassert(rstc);
> >> -		else
> >> +		if (!on)
> >> 
> >>   			reset_control_assert(rstc);
> >> 
> >> -
> >> -		reset_control_put(rstc);
> >> 
> >>   	}
> > 
> > Do we need the CPU part number check for the assertion/deassertion of
> > the reset control?  Surely the DT provides this where appropriate and
> > omits it where it's inappropriate?
> > 
> > If so, I'd separate out the decision whether to error out from the
> > 
> > decision whether to assert the reset control, like this:
> > 	if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> > 	
> > 		pr_err("%s: could not get reset control for core %d\n",
> > 		
> > 		       __func__, pd);
> > 		
> > 		return PTR_ERR(rstc);
> > 	
> > 	}
> > 	
> > 	if (!IS_ERR(rstc) && !on)
> > 	
> > 		reset_control_assert(rstc);
> > 
> > or maybe:
> > 	if (IS_ERR(rstc) && PTR_ERR(rstc) != -ENOENT) {
> > 	
> > 		pr_err("%s: could not get reset control for core %d: %d\n",
> > 		
> > 		       __func__, pd, PTR_ERR(rstc));
> > 		
> > 		return PTR_ERR(rstc);
> > 	
> > 	}
> > 	
> > 	if (!IS_ERR(rstc) && !on)
> > 	
> > 		reset_control_assert(rstc);
> > 
> > which lets you detect whether of_reset_control_get() failed because the
> > reset control was not present (and thus not required) vs failed for some
> > other reason - and this means that the issue of whether the reset
> > control is used is entirely up to the supplied DT file.
> 
> Sound resonable for me.
> 
> I hope get the Heiko and Kever option.
> After all the code is uploaded by Heiko and Kever.

Russell's suggestion is very nice indeed.

We have reset controls for the cpu cores on all Rockchip SoCs but currently 
only absolutely require them on the rk3288, so what Russell suggested handles 
this nicely if we require this later for other SoCs as well (like the A7 ones) 
.


Heiko

> 
> >>   	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
> >> 
> >> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
> >> 
> >>   		}
> >>   	
> >>   	}
> >> 
> >> +	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
> >> +		reset_control_deassert(rstc);
> >> +
> >> +	if (!IS_ERR(rstc))
> >> +		reset_control_put(rstc);
> >> +
> > 
> > and here:
> > 	if (!IS_ERR(rstc)) {
> > 	
> > 		if (on)
> > 		
> > 			reset_control_deassert(rstc);
> > 		
> > 		reset_control_put(rstc);
> > 	
> > 	}
> 
> Ditto.



From thierry.reding at gmail.com  Tue Jun  9 00:53:32 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 9 Jun 2015 09:53:32 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150608163420.GZ7557@n2100.arm.linux.org.uk>
References: <4184159.j0iXe39dFB@phil> <2619686.csNBBFyt8W@phil>
 <20150605110159.GA16254@ulmo.nvidia.com>
 <23123577.mOoqGCAPdL@diego>
 <20150605231058.GQ7557@n2100.arm.linux.org.uk>
 <20150608140256.GA10354@ulmo.nvidia.com>
 <20150608142926.GY7557@n2100.arm.linux.org.uk>
 <20150608154448.GA11103@ulmo.nvidia.com>
 <20150608163420.GZ7557@n2100.arm.linux.org.uk>
Message-ID: <20150609075331.GA28198@ulmo>

On Mon, Jun 08, 2015 at 05:34:21PM +0100, Russell King - ARM Linux wrote:
> On Mon, Jun 08, 2015 at 05:44:53PM +0200, Thierry Reding wrote:
> > On Mon, Jun 08, 2015 at 03:29:26PM +0100, Russell King - ARM Linux wrote:
> > > You're asking questions we have no real answers to - all we have is the
> > > available documentation provided by Freescale - we don't even have the
> > > Rochchip documentation.
> > > 
> > > From the Freescale documentation, which documents the HDMI transmitter
> > > entirely separately from the HDMI phy, I would say that the IP is
> > > structured as two entirely separate blocks, and the chip designer is
> > > free to choose an appropriate phy from a range of HDMI phys.
> > 
> > Does it associate any of the registers with the HDMI PHY? According to
> > the register definitions in drivers/gpu/drm/bridge/dw_hdmi.h the PHY
> > registers are interleaved with other registers that are likely part of
> > the HDMI transmitter proper (there are things like HDCP and CEC engines
> > in that IP as well).
> 
> The protocol stuff is handled by the HDMI Tx - the phy is the conversion
> from the internal digital to the interface domain.
> 
> I could write lots to describe it, but really, the best thing to do is
> to download the iMX6 documentation and take a peek at it...
> 
> https://community.freescale.com/docs/DOC-101840
> 
> Particularly, look at the HDMI 3D Phy section, the system level block
> diagram (34.1.5.1), and 34.2.1 which has the top level I/O diagram for
> just the 3D phy.
> 
> The previous section (section 33) covers the HDMI Tx.

Okay, that matches the picture that's been forming in my mind after
reading the code.

> > > Moreover, in the feature list for the HDMI transmitter, it says (though
> > > this is not applicable to iMX6 - and is probably lifted from the
> > > Synopsis documentation):
> > > 
> > > "* Option to remove pixel repetition clock from HDMI TX interface for an
> > >   easy integration with third party HDMI TX PHYs"
> > > 
> > > So - here's the question: what do we do when we find something using the
> > > Synopsis design-ware HDMI transmitter with a different HDMI phy?
> > > 
> > > Remember, VP, VPH, VP_FILT_* are all part of the HDMI phy according to
> > > the freescale documentation, and not part of the HDMI transmitter.
> > > 
> > > > I
> > > > see register definitions for a "source" PHY and a "master" PHY, where
> > > > the latter seems to be an I2C controller rather than a PHY. Perhaps it
> > > > is used to communicate with an external PHY?
> > > 
> > > I'm not sure where you get that from.  Maybe you could give a chapter
> > > reference?
> > 
> > That's just from skimming drivers/gpu/drm/bridge/dw_hdmi.h (register
> > offsets 0x3000 and the following). The large gap between them and the
> > preceding FC registers could be an additional indication that they are
> > indeed separate IP blocks. Then again, the AUD registers start at an
> > offset of 0x3100, so maybe it's no indication at all.
> 
> Ah, you're getting slightly confused.
> 
> All those registers are to do with the HDMI Tx itself.  The block at
> 0x3000 to 0x3007 is to do with the HDMI Tx receiving various status
> signals from the HDMI Phy, such as HPD, rxsense, and whether the phy
> PLL is locked (which I'm fairly certain is mis-described, as there is
> no output signal from the phy to indicate this, but there is a TX_READY
> signal.)
> 
> The set at 0x3020-0x3032 are to do with talking to the HDMI phy over
> the dedicated I2C interface integrated into the HDMI Tx.  All the
> HDMI Phy registers are accessed through this I2C interface.

Good, that also matches what I understood from reading the driver code.

> > > What if someone designs a chip with their own HDMI phy which uses
> > > different supplies?
> > 
> > That's really one more reason to write proper drivers for the PHYs. If
> > you really ever have to deal with a different PHY chances are that more
> > than just the supplies will be different, in which case you'd need to
> > somehow also abstract away the interoperation between HDMI transmitter
> > and PHY.
> 
> Exactly, but that didn't happen before this code moved out of
> drivers/staging, which is rather unfortunate, but everyone was too busy
> to put much thought into that.
> 
> This is one of the problems when drivers are taken from BSPs rather than
> going away and writing something from documentation: if you start afresh,
> you can model the code according to the documentation without any of the
> original BSP decisions in place.  If you start from the BSP code, you
> have a whole pile of changes you need to identify, and it's very easy to
> overlook something, because what you have works.
> 
> It's something which _should_ be done nevertheless.  The problem is
> finding someone with the time and motivation to do a good job.

Interestingly, though, it seems like the PHYs for both i.MX and Rockchip
are register-compatible because they work with the same driver code. It
could be coincidence, or simply that they both use some standard PHY as
provided by DW along with the HDMI transmitter IP.

Most importantly, like you said, any "damage" has already been done and
in order to keep devices working with existing DTBs we'll have to add
fallback code for backwards-compatibility. I'm thinking instantiating
I2C clients for drivers matching the i.MX/Rockchip code directly from
the HDMI bridge driver if no child nodes are found in DTB.

As for finding somebody with the motivation and time to do it, I suspect
we could just wait for the next user of DW HDMI IP and let them deal
with it. Perhaps documenting our findings in the driver would be helpful
if that time comes.

For the matter at hand, I think we all agree that keeping the supplies
Rockchip-specific for now is the right thing to do.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150609/9730932a/attachment.sig>

From wxt at rock-chips.com  Tue Jun  9 02:49:56 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  9 Jun 2015 17:49:56 +0800
Subject: [PATCH v6 0/3] ARM: rockchip: fix the SMP
Message-ID: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>

Verified on url =
    https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14
Tested by 179200 cycles are pass with CPU up/dowm test scripts.

Changes in v6:
- As Russell suggestion, detect whether of_reset_control_get() failed
- add the comment for 1ms delay.
Series-changes: 5
- back to v2 cpu on/off flow, As Heiko point out in patch v3.
- delay more time in rockchip_boot_secondary().
  From CPU up/down tests, Needed more time to complete CPU process.
  In order to ensure a more, Here that be delayed 1ms.
Series-changes: 4
- Add reset_control_put(rstc) for the non-error case.
Series-changes: 3
- FIx the PATCH v2, it doesn't work on chromium 3.14.
Series-changes: 2
- As Heiko suggestion, re-adjust the cpu on/off flow.
  CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
  CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert
- Fix the delay 1ms describing.
Series-changes: 5
- Fix the patch decription.
- Add the changelog.
Series-changes: 2
- As Kever points out, Fix the subject typo WFI/WFE.
- fix the commnet Unified format.
Series-changes: 5
- Add the changelog.
Series-changes: 2
- Use the checkpatch.pl -f --subjective to check.

Caesar Wang (3):
  ARM: rockchip: fix the CPU soft reset
  ARM: rockchip: ensure CPU to enter WFI/WFE state
  ARM: rockchip: fix the SMP code style

 arch/arm/mach-rockchip/platsmp.c | 58 ++++++++++++++++++++++++----------------
 1 file changed, 35 insertions(+), 23 deletions(-)

-- 
1.9.1



From wxt at rock-chips.com  Tue Jun  9 02:49:57 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  9 Jun 2015 17:49:57 +0800
Subject: [PATCH v6 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433843400-24831-2-git-send-email-wxt@rock-chips.com>

We need different orderings when turning a core on and turning a core
off.  In one case we need to assert reset before turning power off.
In ther other case we need to turn power on and the deassert reset.

In general, the correct flow is:

CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert

This is needed for stressing CPU up/down, as per:
    cd /sys/devices/system/cpu/
    for i in $(seq 10000); do
        echo "================= $i ============"
        for j in $(seq 100); do
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
                echo 0 > cpu1/online
                echo 0 > cpu2/online
                echo 0 > cpu3/online
            done
            while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
                echo 1 > cpu1/online
                echo 1 > cpu2/online
                echo 1 > cpu3/online
            done
        done
    done

The following is reproducable log:
    [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
    [34466.186824] Disabling non-boot CPUs ...
    [34466.187509] CPU1: shutdown
    [34466.188672] CPU2: shutdown
    [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
    .......
or others similar log:
    .......
    [ 4072.454453] CPU1: shutdown
    [ 4072.504436] CPU2: shutdown
    [ 4072.554426] CPU3: shutdown
    [ 4072.577827] CPU1: Booted secondary processor
    [ 4072.582611] CPU2: Booted secondary processor
    <hang>

    Tested by cpu up/down scripts, the results told us need delay more time
before write the sram. The wait time is affected by many aspects
(e.g: cpu frequency, bootrom frequency, sram frequency, bus speed, ...).

    Although the cpus other than cpu0 will write the sram, the speedy is
no the same as cpu0, if the cpu0 early wake up, perhaps the other cpus
can't startup. As we know, the cpu0 can wake up when the cpu1/2/3 write
the 'sram+4/8' and send the sev.
    Anyway.....
    At the moment, 1ms delay will be happy work for cpu up/down scripts test.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>
Reviewed-by: Doug Anderson <dianders at chromium.org>

---

Changes in v6:
- As Russell suggestion, detect whether of_reset_control_get() failed
- add the comment for 1ms delay.
Series-changes: 5
- back to v2 cpu on/off flow, As Heiko point out in patch v3.
- delay more time in rockchip_boot_secondary().
  From CPU up/down tests, Needed more time to complete CPU process.
  In order to ensure a more, Here that be delayed 1ms.
Series-changes: 4
- Add reset_control_put(rstc) for the non-error case.
Series-changes: 3
- FIx the PATCH v2, it doesn't work on chromium 3.14.
Series-changes: 2
- As Heiko suggestion, re-adjust the cpu on/off flow.
  CPU off:
    reset_control_assert
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
    wait_for_power_domain_to_turn_off
  CPU on:
    regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
    wait_for_power_domain_to_turn_on
    reset_control_deassert

 arch/arm/mach-rockchip/platsmp.c | 37 ++++++++++++++++++++-----------------
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index 5b4ca3c..b379cc8 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -72,29 +72,22 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
 static int pmu_set_power_domain(int pd, bool on)
 {
 	u32 val = (on) ? 0 : BIT(pd);
+	struct reset_control *rstc = rockchip_get_core_reset(pd);
 	int ret;
 
+	if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
+		pr_err("%s: could not get reset control for core %d\n",
+		       __func__, pd);
+		return PTR_ERR(rstc);
+	}
+
 	/*
 	 * We need to soft reset the cpu when we turn off the cpu power domain,
 	 * or else the active processors might be stalled when the individual
 	 * processor is powered down.
 	 */
-	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
-		struct reset_control *rstc = rockchip_get_core_reset(pd);
-
-		if (IS_ERR(rstc)) {
-			pr_err("%s: could not get reset control for core %d\n",
-			       __func__, pd);
-			return PTR_ERR(rstc);
-		}
-
-		if (on)
-			reset_control_deassert(rstc);
-		else
-			reset_control_assert(rstc);
-
-		reset_control_put(rstc);
-	}
+	if (!IS_ERR(rstc) && !on)
+		reset_control_assert(rstc);
 
 	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
 	if (ret < 0) {
@@ -112,6 +105,12 @@ static int pmu_set_power_domain(int pd, bool on)
 		}
 	}
 
+	if (!IS_ERR(rstc)) {
+		if (on)
+			reset_control_deassert(rstc);
+		reset_control_put(rstc);
+	}
+
 	return 0;
 }
 
@@ -147,8 +146,12 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * the mailbox:
 		 * sram_base_addr + 4: 0xdeadbeaf
 		 * sram_base_addr + 8: start address for pc
+		 * The cpu0 need to wait the other cpus other than cpu0 entering
+		 * the wfe state.The wait time is affected by many aspects.
+		 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
 		 * */
-		udelay(10);
+		mdelay(1); /* ensure the cpus other than cpu0 to startup */
+
 		writel(virt_to_phys(rockchip_secondary_startup),
 			sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
-- 
1.9.1



From wxt at rock-chips.com  Tue Jun  9 02:49:58 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  9 Jun 2015 17:49:58 +0800
Subject: [PATCH v6 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433843400-24831-3-git-send-email-wxt@rock-chips.com>

The patch can ensure that v7_exit_coherency_flush() in rockchip_cpu_die()
executed in time.
The mdelay(1) has enough time to fix the problem of CPU offlining.
That's a workaround way in rockchip hotplug code,
At least, we haven't a better way to solve it. Who know,
that maybe fixed by chip (hardware) in the future.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v6:
- Fix the delay 1ms describing.
Series-changes: 5
- Fix the patch decription.
- Add the changelog.
Series-changes: 2
- As Kever points out, Fix the subject typo WFI/WFE.

 arch/arm/mach-rockchip/platsmp.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index b379cc8..d629206 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -322,6 +322,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
 #ifdef CONFIG_HOTPLUG_CPU
 static int rockchip_cpu_kill(unsigned int cpu)
 {
+	/*
+	 * We need a delay here to ensure that the dying CPU can finish
+	 * executing v7_coherency_exit() and reach the WFI/WFE state
+	 * prior to having the power domain disabled.
+	 */
+	mdelay(1);
+
 	pmu_set_power_domain(0 + cpu, false);
 	return 1;
 }
-- 
1.9.1



From wxt at rock-chips.com  Tue Jun  9 02:49:59 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue,  9 Jun 2015 17:49:59 +0800
Subject: [PATCH v6 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1433843400-24831-4-git-send-email-wxt@rock-chips.com>

Use the below scripts to check:
scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v6:
- fix the commnet Unified format.
Series-changes: 5
- Add the changelog.
Series-changes: 2
- Use the checkpatch.pl -f --subjective to check.

 arch/arm/mach-rockchip/platsmp.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
index d629206..30ccb82 100644
--- a/arch/arm/mach-rockchip/platsmp.c
+++ b/arch/arm/mach-rockchip/platsmp.c
@@ -100,7 +100,7 @@ static int pmu_set_power_domain(int pd, bool on)
 		ret = pmu_power_domain_is_on(pd);
 		if (ret < 0) {
 			pr_err("%s: could not read power domain state\n",
-				 __func__);
+			       __func__);
 			return ret;
 		}
 	}
@@ -130,7 +130,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 
 	if (cpu >= ncores) {
 		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
-							__func__, cpu, ncores);
+		       __func__, cpu, ncores);
 		return -ENXIO;
 	}
 
@@ -140,7 +140,8 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		return ret;
 
 	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
-		/* We communicate with the bootrom to active the cpus other
+		/*
+		 * We communicate with the bootrom to active the cpus other
 		 * than cpu0, after a blob of initialize code, they will
 		 * stay at wfe state, once they are actived, they will check
 		 * the mailbox:
@@ -149,11 +150,11 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
 		 * The cpu0 need to wait the other cpus other than cpu0 entering
 		 * the wfe state.The wait time is affected by many aspects.
 		 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
-		 * */
+		 */
 		mdelay(1); /* ensure the cpus other than cpu0 to startup */
 
 		writel(virt_to_phys(rockchip_secondary_startup),
-			sram_base_addr + 8);
+		       sram_base_addr + 8);
 		writel(0xDEADBEAF, sram_base_addr + 4);
 		dsb_sev();
 	}
@@ -336,7 +337,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
 static void rockchip_cpu_die(unsigned int cpu)
 {
 	v7_exit_coherency_flush(louis);
-	while(1)
+	while (1)
 		cpu_do_idle();
 }
 #endif
@@ -349,4 +350,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
 	.cpu_die		= rockchip_cpu_die,
 #endif
 };
+
 CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
-- 
1.9.1



From wxt at rock-chips.com  Tue Jun  9 02:55:40 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 09 Jun 2015 17:55:40 +0800
Subject: [PATCH v5 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <55760F0F.9010302@rock-chips.com>
References: <1433747496-7642-1-git-send-email-wxt@rock-chips.com>
 <1433747496-7642-2-git-send-email-wxt@rock-chips.com>
 <20150608092416.GV7557@n2100.arm.linux.org.uk>
 <55760F0F.9010302@rock-chips.com>
Message-ID: <5576B81C.6030904@rock-chips.com>



? 2015?06?09? 05:54, Caesar Wang ??:
>
>
> ? 2015?06?08? 17:24, Russell King - ARM Linux ??:
>> On Mon, Jun 08, 2015 at 03:11:34PM +0800, Caesar Wang wrote:
>>> We need different orderings when turning a core on and turning a core
>>> off.  In one case we need to assert reset before turning power off.
>>> In ther other case we need to turn power on and the deassert reset.
>>>
>>> In general, the correct flow is:
>>>
>>> CPU off:
>>>      reset_control_assert
>>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>>>      wait_for_power_domain_to_turn_off
>>> CPU on:
>>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>>>      wait_for_power_domain_to_turn_on
>>>      reset_control_deassert
>>>
>>> This is needed for stressing CPU up/down, as per:
>>>      cd /sys/devices/system/cpu/
>>>      for i in $(seq 10000); do
>>>          echo "================= $i ============"
>>>          for j in $(seq 100); do
>>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat 
>>> cpu3/online)" != "000"" ]]
>>>                  echo 0 > cpu1/online
>>>                  echo 0 > cpu2/online
>>>                  echo 0 > cpu3/online
>>>              done
>>>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat 
>>> cpu3/online)" != "111" ]]; do
>>>                  echo 1 > cpu1/online
>>>                  echo 1 > cpu2/online
>>>                  echo 1 > cpu3/online
>>>              done
>>>          done
>>>      done
>>>
>>> The following is reproducile log:
>> "reproducable"
>>
>>>      [34466.186812] PM: noirq suspend of devices complete after 
>>> 0.669 msecs
>>>      [34466.186824] Disabling non-boot CPUs ...
>>>      [34466.187509] CPU1: shutdown
>>>      [34466.188672] CPU2: shutdown
>>>      [34473.736627] Kernel panic - not syncing:Watchdog detected 
>>> hard LOCKUP on cpu 0
>>>      .......
>>> or others similar log:
>>>      .......
>>>      [ 4072.454453] CPU1: shutdown
>>>      [ 4072.504436] CPU2: shutdown
>>>      [ 4072.554426] CPU3: shutdown
>>>      [ 4072.577827] CPU1: Booted secondary processor
>>>      [ 4072.582611] CPU2: Booted secondary processor
>>>      [ 4072.587426] CPU3: Booted secondary processor
>>>      <hang>
>>>
>>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>>> Reviewed-by: Doug Anderson <dianders at chromium.org>
>>>
>>> Changes in v5:
>>>      - back to v2 cpu on/off flow, As Heiko point out in patch v3.
>>>      - delay more time in rockchip_boot_secondary().
>>>      From CPU up/down tests, Needed more time to complete CPU process.
>>>      In order to ensure a more, Here that be delayed 1ms.
>>>
>>> Changes in v4:
>>>      - Add reset_control_put(rstc) for the non-error case.
>>>
>>> Changes in v3:
>>>      - FIx the PATCH v2, it doesn't work on chromium 3.14.
>>>
>>> Changes in v2:
>>>      - As Heiko suggestion, re-adjust the cpu on/off flow.
>>>      CPU off:
>>>      reset_control_assert
>>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>>>      wait_for_power_domain_to_turn_off
>>>      CPU on:
>>>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>>>      wait_for_power_domain_to_turn_on
>>>      reset_control_deassert
>>>
>>> ---
>>>
>>>   arch/arm/mach-rockchip/platsmp.c | 18 ++++++++++--------
>>>   1 file changed, 10 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-rockchip/platsmp.c 
>>> b/arch/arm/mach-rockchip/platsmp.c
>>> index 5b4ca3c..bd40852 100644
>>> --- a/arch/arm/mach-rockchip/platsmp.c
>>> +++ b/arch/arm/mach-rockchip/platsmp.c
>>> @@ -72,6 +72,7 @@ static struct reset_control 
>>> *rockchip_get_core_reset(int cpu)
>>>   static int pmu_set_power_domain(int pd, bool on)
>>>   {
>>>       u32 val = (on) ? 0 : BIT(pd);
>>> +    struct reset_control *rstc = rockchip_get_core_reset(pd);
>>>       int ret;
>>>         /*
>>> @@ -80,20 +81,15 @@ static int pmu_set_power_domain(int pd, bool on)
>>>        * processor is powered down.
>>>        */
>>>       if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
>>> -        struct reset_control *rstc = rockchip_get_core_reset(pd);
>>> -
>>> +        /* We only require the reset on the RK3288 at the moment */
>>>           if (IS_ERR(rstc)) {
>>>               pr_err("%s: could not get reset control for core %d\n",
>>>                      __func__, pd);
>>>               return PTR_ERR(rstc);
>>>           }
>>>   -        if (on)
>>> -            reset_control_deassert(rstc);
>>> -        else
>>> +        if (!on)
>>>               reset_control_assert(rstc);
>>> -
>>> -        reset_control_put(rstc);
>>>       }
>>>         ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>>> @@ -112,6 +108,12 @@ static int pmu_set_power_domain(int pd, bool on)
>>>           }
>>>       }
>>>   +    if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9 && on)
>>> +        reset_control_deassert(rstc);
>>> +
>>> +    if (!IS_ERR(rstc))
>>> +        reset_control_put(rstc);
>>> +
>>>       return 0;
>>>   }
>>>   @@ -148,7 +150,7 @@ static int __cpuinit 
>>> rockchip_boot_secondary(unsigned int cpu,
>>>            * sram_base_addr + 4: 0xdeadbeaf
>>>            * sram_base_addr + 8: start address for pc
>>>            * */
>>> -        udelay(10);
>>> +        mdelay(1);
>> The reason for this delay needs a comment, as it's not obvious why you
>> would need to delay before writing to the SRAM.  Also documenting in
>> a comment why the delay is necessary would be good.
>>
>
> Sorry for delay, I wait a better solution for this.
> We don't need any 10us delay or 1m delay, I think.
>
> -        udelay(10);
>
> +        while (readl(sram_base_addr + 4 ) != 1); //lock =1
>
>
> We need do that if i'm correct from the bootrom code.
> Tested are pass over 120000 cycles on today, I will wait more testing 
> cycles to confirm that's ok.
>

Please forget it!

It's helpful that be caused by adding a log.:-(

>
>

-- 
Thanks,
- Caesar




From dianders at chromium.org  Tue Jun  9 11:17:49 2015
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 9 Jun 2015 11:17:49 -0700
Subject: [PATCH v6 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433843400-24831-4-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-4-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=V31o3Jj-26hiSHMikAbWw3x4p=NqUW-tca2xqUxmjgsA@mail.gmail.com>

Caesar,

On Tue, Jun 9, 2015 at 2:49 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> Use the below scripts to check:
> scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>
> ---
>
> Changes in v6:
> - fix the commnet Unified format.
> Series-changes: 5
> - Add the changelog.
> Series-changes: 2
> - Use the checkpatch.pl -f --subjective to check.
>
>  arch/arm/mach-rockchip/platsmp.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)

This patch hasn't changed, so you could have kept my Reviewed-by that
I gave previously.

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From dianders at chromium.org  Tue Jun  9 11:16:56 2015
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 9 Jun 2015 11:16:56 -0700
Subject: [PATCH v6 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433843400-24831-2-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-2-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=VQaD-VSmiNXTNdFnhKZZPXQwDW5BVBB+XJCJfKswbycA@mail.gmail.com>

Caesar,

On Tue, Jun 9, 2015 at 2:49 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
>
> In general, the correct flow is:
>
> CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>     wait_for_power_domain_to_turn_off
> CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     wait_for_power_domain_to_turn_on
>     reset_control_deassert
>
> This is needed for stressing CPU up/down, as per:
>     cd /sys/devices/system/cpu/
>     for i in $(seq 10000); do
>         echo "================= $i ============"
>         for j in $(seq 100); do
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
>                 echo 0 > cpu1/online
>                 echo 0 > cpu2/online
>                 echo 0 > cpu3/online
>             done
>             while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
>                 echo 1 > cpu1/online
>                 echo 1 > cpu2/online
>                 echo 1 > cpu3/online
>             done
>         done
>     done
>
> The following is reproducable log:
>     [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>     [34466.186824] Disabling non-boot CPUs ...
>     [34466.187509] CPU1: shutdown
>     [34466.188672] CPU2: shutdown
>     [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
>     .......
> or others similar log:
>     .......
>     [ 4072.454453] CPU1: shutdown
>     [ 4072.504436] CPU2: shutdown
>     [ 4072.554426] CPU3: shutdown
>     [ 4072.577827] CPU1: Booted secondary processor
>     [ 4072.582611] CPU2: Booted secondary processor
>     <hang>
>
>     Tested by cpu up/down scripts, the results told us need delay more time
> before write the sram. The wait time is affected by many aspects
> (e.g: cpu frequency, bootrom frequency, sram frequency, bus speed, ...).
>
>     Although the cpus other than cpu0 will write the sram, the speedy is
> no the same as cpu0, if the cpu0 early wake up, perhaps the other cpus
> can't startup. As we know, the cpu0 can wake up when the cpu1/2/3 write
> the 'sram+4/8' and send the sev.
>     Anyway.....
>     At the moment, 1ms delay will be happy work for cpu up/down scripts test.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Reviewed-by: Doug Anderson <dianders at chromium.org>

Usually it's good to remove someone's "Reviewed-by" when you've made
as many changes as you have.  ...but in this case I am still happy
with this patch, so I'll re-assert:

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From dianders at chromium.org  Tue Jun  9 11:13:19 2015
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 9 Jun 2015 11:13:19 -0700
Subject: [PATCH v6 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433843400-24831-3-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-3-git-send-email-wxt@rock-chips.com>
Message-ID: <CAD=FV=W63LxYJtm=YyNmQynnL8SEJc6DkOtNQahnfVw=m0eBPw@mail.gmail.com>

Caesar,

On Tue, Jun 9, 2015 at 2:49 AM, Caesar Wang <wxt at rock-chips.com> wrote:
> The patch can ensure that v7_exit_coherency_flush() in rockchip_cpu_die()
> executed in time.
> The mdelay(1) has enough time to fix the problem of CPU offlining.
> That's a workaround way in rockchip hotplug code,
> At least, we haven't a better way to solve it. Who know,
> that maybe fixed by chip (hardware) in the future.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>
> ---
>
> Changes in v6:
> - Fix the delay 1ms describing.
> Series-changes: 5
> - Fix the patch decription.
> - Add the changelog.
> Series-changes: 2
> - As Kever points out, Fix the subject typo WFI/WFE.
>
>  arch/arm/mach-rockchip/platsmp.c | 7 +++++++
>  1 file changed, 7 insertions(+)

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From heiko at sntech.de  Tue Jun  9 13:04:08 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 09 Jun 2015 22:04:08 +0200
Subject: [PATCH v6 0/3] ARM: rockchip: fix the SMP
In-Reply-To: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
Message-ID: <4374173.2rp7Jv3Cd5@diego>

Hi Caesar,


Am Dienstag, 9. Juni 2015, 17:49:56 schrieb Caesar Wang:
> Verified on url =
>    
> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-> 3.14 Tested by 179200 cycles are pass with CPU up/dowm test scripts.
> 
> Changes in v6:
> - As Russell suggestion, detect whether of_reset_control_get() failed
> - add the comment for 1ms delay.
> Series-changes: 5
> - back to v2 cpu on/off flow, As Heiko point out in patch v3.
> - delay more time in rockchip_boot_secondary().
>   From CPU up/down tests, Needed more time to complete CPU process.
>   In order to ensure a more, Here that be delayed 1ms.
> Series-changes: 4
> - Add reset_control_put(rstc) for the non-error case.
> Series-changes: 3
> - FIx the PATCH v2, it doesn't work on chromium 3.14.
> Series-changes: 2
> - As Heiko suggestion, re-adjust the cpu on/off flow.
>   CPU off:
>     reset_control_assert
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>     wait_for_power_domain_to_turn_off
>   CPU on:
>     regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>     wait_for_power_domain_to_turn_on
>     reset_control_deassert
> - Fix the delay 1ms describing.
> Series-changes: 5
> - Fix the patch decription.
> - Add the changelog.
> Series-changes: 2
> - As Kever points out, Fix the subject typo WFI/WFE.
> - fix the commnet Unified format.
> Series-changes: 5
> - Add the changelog.
> Series-changes: 2
> - Use the checkpatch.pl -f --subjective to check.
> 
> Caesar Wang (3):
>   ARM: rockchip: fix the CPU soft reset
>   ARM: rockchip: ensure CPU to enter WFI/WFE state
>   ARM: rockchip: fix the SMP code style

the series looks good to me now. I'll give it another day or so before 
applying, just in case Russell wants to provide additional comments.


Heiko



From heiko at sntech.de  Tue Jun  9 16:29:43 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Wed, 10 Jun 2015 01:29:43 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150609075331.GA28198@ulmo>
References: <4184159.j0iXe39dFB@phil>
 <20150608163420.GZ7557@n2100.arm.linux.org.uk> <20150609075331.GA28198@ulmo>
Message-ID: <3551826.dyCjorKhLA@diego>

Am Dienstag, 9. Juni 2015, 09:53:32 schrieb Thierry Reding:
> On Mon, Jun 08, 2015 at 05:34:21PM +0100, Russell King - ARM Linux wrote:
> > On Mon, Jun 08, 2015 at 05:44:53PM +0200, Thierry Reding wrote:
> > > On Mon, Jun 08, 2015 at 03:29:26PM +0100, Russell King - ARM Linux 
wrote:
> > > > You're asking questions we have no real answers to - all we have is
> > > > the
> > > > available documentation provided by Freescale - we don't even have the
> > > > Rochchip documentation.
> > > > 
> > > > From the Freescale documentation, which documents the HDMI transmitter
> > > > entirely separately from the HDMI phy, I would say that the IP is
> > > > structured as two entirely separate blocks, and the chip designer is
> > > > free to choose an appropriate phy from a range of HDMI phys.
> > > 
> > > Does it associate any of the registers with the HDMI PHY? According to
> > > the register definitions in drivers/gpu/drm/bridge/dw_hdmi.h the PHY
> > > registers are interleaved with other registers that are likely part of
> > > the HDMI transmitter proper (there are things like HDCP and CEC engines
> > > in that IP as well).
> > 
> > The protocol stuff is handled by the HDMI Tx - the phy is the conversion
> > from the internal digital to the interface domain.
> > 
> > I could write lots to describe it, but really, the best thing to do is
> > to download the iMX6 documentation and take a peek at it...
> > 
> > https://community.freescale.com/docs/DOC-101840
> > 
> > Particularly, look at the HDMI 3D Phy section, the system level block
> > diagram (34.1.5.1), and 34.2.1 which has the top level I/O diagram for
> > just the 3D phy.
> > 
> > The previous section (section 33) covers the HDMI Tx.
> 
> Okay, that matches the picture that's been forming in my mind after
> reading the code.
> 
> > > > Moreover, in the feature list for the HDMI transmitter, it says
> > > > (though
> > > > this is not applicable to iMX6 - and is probably lifted from the
> > > > Synopsis documentation):
> > > > 
> > > > "* Option to remove pixel repetition clock from HDMI TX interface for
> > > > an
> > > > 
> > > >   easy integration with third party HDMI TX PHYs"
> > > > 
> > > > So - here's the question: what do we do when we find something using
> > > > the
> > > > Synopsis design-ware HDMI transmitter with a different HDMI phy?
> > > > 
> > > > Remember, VP, VPH, VP_FILT_* are all part of the HDMI phy according to
> > > > the freescale documentation, and not part of the HDMI transmitter.
> > > > 
> > > > > I
> > > > > see register definitions for a "source" PHY and a "master" PHY,
> > > > > where
> > > > > the latter seems to be an I2C controller rather than a PHY. Perhaps
> > > > > it
> > > > > is used to communicate with an external PHY?
> > > > 
> > > > I'm not sure where you get that from.  Maybe you could give a chapter
> > > > reference?
> > > 
> > > That's just from skimming drivers/gpu/drm/bridge/dw_hdmi.h (register
> > > offsets 0x3000 and the following). The large gap between them and the
> > > preceding FC registers could be an additional indication that they are
> > > indeed separate IP blocks. Then again, the AUD registers start at an
> > > offset of 0x3100, so maybe it's no indication at all.
> > 
> > Ah, you're getting slightly confused.
> > 
> > All those registers are to do with the HDMI Tx itself.  The block at
> > 0x3000 to 0x3007 is to do with the HDMI Tx receiving various status
> > signals from the HDMI Phy, such as HPD, rxsense, and whether the phy
> > PLL is locked (which I'm fairly certain is mis-described, as there is
> > no output signal from the phy to indicate this, but there is a TX_READY
> > signal.)
> > 
> > The set at 0x3020-0x3032 are to do with talking to the HDMI phy over
> > the dedicated I2C interface integrated into the HDMI Tx.  All the
> > HDMI Phy registers are accessed through this I2C interface.
> 
> Good, that also matches what I understood from reading the driver code.
> 
> > > > What if someone designs a chip with their own HDMI phy which uses
> > > > different supplies?
> > > 
> > > That's really one more reason to write proper drivers for the PHYs. If
> > > you really ever have to deal with a different PHY chances are that more
> > > than just the supplies will be different, in which case you'd need to
> > > somehow also abstract away the interoperation between HDMI transmitter
> > > and PHY.
> > 
> > Exactly, but that didn't happen before this code moved out of
> > drivers/staging, which is rather unfortunate, but everyone was too busy
> > to put much thought into that.
> > 
> > This is one of the problems when drivers are taken from BSPs rather than
> > going away and writing something from documentation: if you start afresh,
> > you can model the code according to the documentation without any of the
> > original BSP decisions in place.  If you start from the BSP code, you
> > have a whole pile of changes you need to identify, and it's very easy to
> > overlook something, because what you have works.
> > 
> > It's something which _should_ be done nevertheless.  The problem is
> > finding someone with the time and motivation to do a good job.
> 
> Interestingly, though, it seems like the PHYs for both i.MX and Rockchip
> are register-compatible because they work with the same driver code. It
> could be coincidence, or simply that they both use some standard PHY as
> provided by DW along with the HDMI transmitter IP.
> 
> Most importantly, like you said, any "damage" has already been done and
> in order to keep devices working with existing DTBs we'll have to add
> fallback code for backwards-compatibility. I'm thinking instantiating
> I2C clients for drivers matching the i.MX/Rockchip code directly from
> the HDMI bridge driver if no child nodes are found in DTB.
> 
> As for finding somebody with the motivation and time to do it, I suspect
> we could just wait for the next user of DW HDMI IP and let them deal
> with it. Perhaps documenting our findings in the driver would be helpful
> if that time comes.
> 
> For the matter at hand, I think we all agree that keeping the supplies
> Rockchip-specific for now is the right thing to do.

Yep.

Allthough from the discussion and explanations I've now also got the "don't 
make it worse" feeling, so am somehow reluctant to add supplies that also 
might describe this inadequately.

The Rockchip-specific documentation only lists the two supplies as AVDD_1V0, 
AVDD_1V8 with a description of "DC supply voltage for Analog part of HDMI".
The supplies aren't mentioned otherwise at all, so I guess I'll ponder this a 
bit more at first.


From linux at arm.linux.org.uk  Tue Jun  9 16:36:18 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 10 Jun 2015 00:36:18 +0100
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <3551826.dyCjorKhLA@diego>
References: <4184159.j0iXe39dFB@phil>
 <20150608163420.GZ7557@n2100.arm.linux.org.uk>
 <20150609075331.GA28198@ulmo> <3551826.dyCjorKhLA@diego>
Message-ID: <20150609233618.GK7557@n2100.arm.linux.org.uk>

On Wed, Jun 10, 2015 at 01:29:43AM +0200, Heiko St?bner wrote:
> Allthough from the discussion and explanations I've now also got the "don't 
> make it worse" feeling, so am somehow reluctant to add supplies that also 
> might describe this inadequately.
> 
> The Rockchip-specific documentation only lists the two supplies as AVDD_1V0, 
> AVDD_1V8 with a description of "DC supply voltage for Analog part of HDMI".
> The supplies aren't mentioned otherwise at all, so I guess I'll ponder this a 
> bit more at first.

Are they controllable from software at all?  If they aren't, then
I'd suggest leaving them out until we have a distinction between
the Tx and Phy - much as we do for iMX6.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From kever.yang at rock-chips.com  Tue Jun  9 22:58:47 2015
From: kever.yang at rock-chips.com (Kever Yang)
Date: Wed, 10 Jun 2015 13:58:47 +0800
Subject: [PATCH v6 1/3] ARM: rockchip: fix the CPU soft reset
In-Reply-To: <1433843400-24831-2-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-2-git-send-email-wxt@rock-chips.com>
Message-ID: <5577D217.1010606@rock-chips.com>

Hi Caesar,

On 06/09/2015 05:49 PM, Caesar Wang wrote:
> We need different orderings when turning a core on and turning a core
> off.  In one case we need to assert reset before turning power off.
> In ther other case we need to turn power on and the deassert reset.
>
> In general, the correct flow is:
>
> CPU off:
>      reset_control_assert
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>      wait_for_power_domain_to_turn_off
> CPU on:
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>      wait_for_power_domain_to_turn_on
>      reset_control_deassert
>
> This is needed for stressing CPU up/down, as per:
>      cd /sys/devices/system/cpu/
>      for i in $(seq 10000); do
>          echo "================= $i ============"
>          for j in $(seq 100); do
>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "000"" ]]
>                  echo 0 > cpu1/online
>                  echo 0 > cpu2/online
>                  echo 0 > cpu3/online
>              done
>              while [[ "$(cat cpu1/online)$(cat cpu2/online)$(cat cpu3/online)" != "111" ]]; do
>                  echo 1 > cpu1/online
>                  echo 1 > cpu2/online
>                  echo 1 > cpu3/online
>              done
>          done
>      done
>
> The following is reproducable log:
>      [34466.186812] PM: noirq suspend of devices complete after 0.669 msecs
>      [34466.186824] Disabling non-boot CPUs ...
>      [34466.187509] CPU1: shutdown
>      [34466.188672] CPU2: shutdown
>      [34473.736627] Kernel panic - not syncing:Watchdog detected hard LOCKUP on cpu 0
>      .......
> or others similar log:
>      .......
>      [ 4072.454453] CPU1: shutdown
>      [ 4072.504436] CPU2: shutdown
>      [ 4072.554426] CPU3: shutdown
>      [ 4072.577827] CPU1: Booted secondary processor
>      [ 4072.582611] CPU2: Booted secondary processor
>      <hang>
>
>      Tested by cpu up/down scripts, the results told us need delay more time
> before write the sram. The wait time is affected by many aspects
> (e.g: cpu frequency, bootrom frequency, sram frequency, bus speed, ...).
>
>      Although the cpus other than cpu0 will write the sram, the speedy is
> no the same as cpu0, if the cpu0 early wake up, perhaps the other cpus
> can't startup. As we know, the cpu0 can wake up when the cpu1/2/3 write
> the 'sram+4/8' and send the sev.
>      Anyway.....
>      At the moment, 1ms delay will be happy work for cpu up/down scripts test.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
> Reviewed-by: Doug Anderson <dianders at chromium.org>
>
> ---
>
> Changes in v6:
> - As Russell suggestion, detect whether of_reset_control_get() failed
> - add the comment for 1ms delay.
> Series-changes: 5
> - back to v2 cpu on/off flow, As Heiko point out in patch v3.
> - delay more time in rockchip_boot_secondary().
>    From CPU up/down tests, Needed more time to complete CPU process.
>    In order to ensure a more, Here that be delayed 1ms.
> Series-changes: 4
> - Add reset_control_put(rstc) for the non-error case.
> Series-changes: 3
> - FIx the PATCH v2, it doesn't work on chromium 3.14.
> Series-changes: 2
> - As Heiko suggestion, re-adjust the cpu on/off flow.
>    CPU off:
>      reset_control_assert
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), BIT(pd))
>      wait_for_power_domain_to_turn_off
>    CPU on:
>      regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), 0)
>      wait_for_power_domain_to_turn_on
>      reset_control_deassert
>
>   arch/arm/mach-rockchip/platsmp.c | 37 ++++++++++++++++++++-----------------
>   1 file changed, 20 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index 5b4ca3c..b379cc8 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -72,29 +72,22 @@ static struct reset_control *rockchip_get_core_reset(int cpu)
>   static int pmu_set_power_domain(int pd, bool on)
>   {
>   	u32 val = (on) ? 0 : BIT(pd);
> +	struct reset_control *rstc = rockchip_get_core_reset(pd);
>   	int ret;
>   
> +	if (IS_ERR(rstc) && read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> +		pr_err("%s: could not get reset control for core %d\n",
> +		       __func__, pd);
> +		return PTR_ERR(rstc);
> +	}
> +
>   	/*
>   	 * We need to soft reset the cpu when we turn off the cpu power domain,
>   	 * or else the active processors might be stalled when the individual
>   	 * processor is powered down.
>   	 */
> -	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> -		struct reset_control *rstc = rockchip_get_core_reset(pd);
> -
> -		if (IS_ERR(rstc)) {
> -			pr_err("%s: could not get reset control for core %d\n",
> -			       __func__, pd);
> -			return PTR_ERR(rstc);
> -		}
> -
> -		if (on)
> -			reset_control_deassert(rstc);
> -		else
> -			reset_control_assert(rstc);
> -
> -		reset_control_put(rstc);
> -	}
> +	if (!IS_ERR(rstc) && !on)
> +		reset_control_assert(rstc);
>   
>   	ret = regmap_update_bits(pmu, PMU_PWRDN_CON, BIT(pd), val);
>   	if (ret < 0) {
> @@ -112,6 +105,12 @@ static int pmu_set_power_domain(int pd, bool on)
>   		}
>   	}
>   
> +	if (!IS_ERR(rstc)) {
> +		if (on)
> +			reset_control_deassert(rstc);
> +		reset_control_put(rstc);
> +	}
> +
>   	return 0;
>   }
>   
> @@ -147,8 +146,12 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>   		 * the mailbox:
>   		 * sram_base_addr + 4: 0xdeadbeaf
>   		 * sram_base_addr + 8: start address for pc
> +		 * The cpu0 need to wait the other cpus other than cpu0 entering
> +		 * the wfe state.The wait time is affected by many aspects.
> +		 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
>   		 * */
> -		udelay(10);
> +		mdelay(1); /* ensure the cpus other than cpu0 to startup */
> +
>   		writel(virt_to_phys(rockchip_secondary_startup),
>   			sram_base_addr + 8);
>   		writel(0xDEADBEAF, sram_base_addr + 4);
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>



From kever.yang at rock-chips.com  Tue Jun  9 22:59:51 2015
From: kever.yang at rock-chips.com (Kever Yang)
Date: Wed, 10 Jun 2015 13:59:51 +0800
Subject: [PATCH v6 3/3] ARM: rockchip: fix the SMP code style
In-Reply-To: <1433843400-24831-4-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-4-git-send-email-wxt@rock-chips.com>
Message-ID: <5577D257.4090409@rock-chips.com>

Hi Caesar,

On 06/09/2015 05:49 PM, Caesar Wang wrote:
> Use the below scripts to check:
> scripts/checkpatch.pl -f --subject arch/arm/mach-rockchip/platsmp.c
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>
> ---
>
> Changes in v6:
> - fix the commnet Unified format.
> Series-changes: 5
> - Add the changelog.
> Series-changes: 2
> - Use the checkpatch.pl -f --subjective to check.
>
>   arch/arm/mach-rockchip/platsmp.c | 14 ++++++++------
>   1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index d629206..30ccb82 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -100,7 +100,7 @@ static int pmu_set_power_domain(int pd, bool on)
>   		ret = pmu_power_domain_is_on(pd);
>   		if (ret < 0) {
>   			pr_err("%s: could not read power domain state\n",
> -				 __func__);
> +			       __func__);
>   			return ret;
>   		}
>   	}
> @@ -130,7 +130,7 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>   
>   	if (cpu >= ncores) {
>   		pr_err("%s: cpu %d outside maximum number of cpus %d\n",
> -							__func__, cpu, ncores);
> +		       __func__, cpu, ncores);
>   		return -ENXIO;
>   	}
>   
> @@ -140,7 +140,8 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>   		return ret;
>   
>   	if (read_cpuid_part() != ARM_CPU_PART_CORTEX_A9) {
> -		/* We communicate with the bootrom to active the cpus other
> +		/*
> +		 * We communicate with the bootrom to active the cpus other
>   		 * than cpu0, after a blob of initialize code, they will
>   		 * stay at wfe state, once they are actived, they will check
>   		 * the mailbox:
> @@ -149,11 +150,11 @@ static int __cpuinit rockchip_boot_secondary(unsigned int cpu,
>   		 * The cpu0 need to wait the other cpus other than cpu0 entering
>   		 * the wfe state.The wait time is affected by many aspects.
>   		 * (e.g: cpu frequency, bootrom frequency, sram frequency, ...)
> -		 * */
> +		 */
>   		mdelay(1); /* ensure the cpus other than cpu0 to startup */
>   
>   		writel(virt_to_phys(rockchip_secondary_startup),
> -			sram_base_addr + 8);
> +		       sram_base_addr + 8);
>   		writel(0xDEADBEAF, sram_base_addr + 4);
>   		dsb_sev();
>   	}
> @@ -336,7 +337,7 @@ static int rockchip_cpu_kill(unsigned int cpu)
>   static void rockchip_cpu_die(unsigned int cpu)
>   {
>   	v7_exit_coherency_flush(louis);
> -	while(1)
> +	while (1)
>   		cpu_do_idle();
>   }
>   #endif
> @@ -349,4 +350,5 @@ static struct smp_operations rockchip_smp_ops __initdata = {
>   	.cpu_die		= rockchip_cpu_die,
>   #endif
>   };
> +
>   CPU_METHOD_OF_DECLARE(rk3066_smp, "rockchip,rk3066-smp", &rockchip_smp_ops);
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>



From kever.yang at rock-chips.com  Tue Jun  9 22:59:16 2015
From: kever.yang at rock-chips.com (Kever Yang)
Date: Wed, 10 Jun 2015 13:59:16 +0800
Subject: [PATCH v6 2/3] ARM: rockchip: ensure CPU to enter WFI/WFE state
In-Reply-To: <1433843400-24831-3-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
 <1433843400-24831-3-git-send-email-wxt@rock-chips.com>
Message-ID: <5577D234.5000502@rock-chips.com>

Hi Caesar,

On 06/09/2015 05:49 PM, Caesar Wang wrote:
> The patch can ensure that v7_exit_coherency_flush() in rockchip_cpu_die()
> executed in time.
> The mdelay(1) has enough time to fix the problem of CPU offlining.
> That's a workaround way in rockchip hotplug code,
> At least, we haven't a better way to solve it. Who know,
> that maybe fixed by chip (hardware) in the future.
>
> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>
> ---
>
> Changes in v6:
> - Fix the delay 1ms describing.
> Series-changes: 5
> - Fix the patch decription.
> - Add the changelog.
> Series-changes: 2
> - As Kever points out, Fix the subject typo WFI/WFE.
>
>   arch/arm/mach-rockchip/platsmp.c | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm/mach-rockchip/platsmp.c b/arch/arm/mach-rockchip/platsmp.c
> index b379cc8..d629206 100644
> --- a/arch/arm/mach-rockchip/platsmp.c
> +++ b/arch/arm/mach-rockchip/platsmp.c
> @@ -322,6 +322,13 @@ static void __init rockchip_smp_prepare_cpus(unsigned int max_cpus)
>   #ifdef CONFIG_HOTPLUG_CPU
>   static int rockchip_cpu_kill(unsigned int cpu)
>   {
> +	/*
> +	 * We need a delay here to ensure that the dying CPU can finish
> +	 * executing v7_coherency_exit() and reach the WFI/WFE state
> +	 * prior to having the power domain disabled.
> +	 */
> +	mdelay(1);
> +
>   	pmu_set_power_domain(0 + cpu, false);
>   	return 1;
>   }
Reviewed-by: Kever Yang <kever.yang at rock-chips.com>



From heiko at sntech.de  Wed Jun 10 01:39:22 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Wed, 10 Jun 2015 10:39:22 +0200
Subject: [RFT v2 34/48] pinctrl: Prepare for killing the first parameter
 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-35-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-35-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <4497677.ZpyibMJVfv@diego>

Am Donnerstag, 4. Juni 2015, 12:13:44 schrieb Jiang Liu:
> Change irq flow handler to prepare for killing the first parameter 'irq'
> of irq_flow_handler_t.
> 
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> ---
>  drivers/pinctrl/pinctrl-rockchip.c    |    4 ++--

For Rockchip
Acked-by: Heiko Stuebner <heiko at sntech.de>



From boris.brezillon at free-electrons.com  Fri Jun  5 04:38:03 2015
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Fri, 5 Jun 2015 13:38:03 +0200
Subject: [PATCH v2 1/2] clk: change clk_ops' ->round_rate() prototype
In-Reply-To: <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
References: <1430407809-31147-1-git-send-email-boris.brezillon@free-electrons.com>
 <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
 <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
Message-ID: <20150605133803.59990a66@bbrezillon>

Hi Paul,

On Thu, 4 Jun 2015 23:02:25 +0000 (UTC)
Paul Walmsley <paul at pwsan.com> wrote:

> Hi folks
> 
> just a brief comment on this one:
> 
> On Thu, 30 Apr 2015, Boris Brezillon wrote:
> 
> > Clock rates are stored in an unsigned long field, but ->round_rate()
> > (which returns a rounded rate from a requested one) returns a long
> > value (errors are reported using negative error codes), which can lead
> > to long overflow if the clock rate exceed 2Ghz.
> > 
> > Change ->round_rate() prototype to return 0 or an error code, and pass the
> > requested rate as a pointer so that it can be adjusted depending on
> > hardware capabilities.
> 
> ...
> 
> > diff --git a/Documentation/clk.txt b/Documentation/clk.txt
> > index 0e4f90a..fca8b7a 100644
> > --- a/Documentation/clk.txt
> > +++ b/Documentation/clk.txt
> > @@ -68,8 +68,8 @@ the operations defined in clk.h:
> >  		int		(*is_enabled)(struct clk_hw *hw);
> >  		unsigned long	(*recalc_rate)(struct clk_hw *hw,
> >  						unsigned long parent_rate);
> > -		long		(*round_rate)(struct clk_hw *hw,
> > -						unsigned long rate,
> > +		int		(*round_rate)(struct clk_hw *hw,
> > +						unsigned long *rate,
> >  						unsigned long *parent_rate);
> >  		long		(*determine_rate)(struct clk_hw *hw,
> >  						unsigned long rate,
> 
> I'd suggest that we should probably go straight to 64-bit rates.  There 
> are already plenty of clock sources that can generate rates higher than 
> 4GiHz.

Yep, that was something I was considering too. If Stephen agrees I'll
change that in the next version.
BTW, you're referring to the second version of this patch, but things
have changed a bit: Stephen recommended to only modify the
->determine_rate() prototype and pass a structure instead of a list of
arguments.
Here is the last version of this series [1].

Best Regards,

Boris

[1]http://patchwork.linux-mips.org/patch/10092/

-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com


From boris.brezillon at free-electrons.com  Fri Jun  5 04:39:28 2015
From: boris.brezillon at free-electrons.com (Boris Brezillon)
Date: Fri, 5 Jun 2015 13:39:28 +0200
Subject: [PATCH v2 1/2] clk: change clk_ops' ->round_rate() prototype
In-Reply-To: <557161D1.3040107@nvidia.com>
References: <1430407809-31147-1-git-send-email-boris.brezillon@free-electrons.com>
 <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
 <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
 <557161D1.3040107@nvidia.com>
Message-ID: <20150605133928.66909901@bbrezillon>

Hi Jon,

On Fri, 5 Jun 2015 09:46:09 +0100
Jon Hunter <jonathanh at nvidia.com> wrote:

> 
> On 05/06/15 00:02, Paul Walmsley wrote:
> > Hi folks
> > 
> > just a brief comment on this one:
> > 
> > On Thu, 30 Apr 2015, Boris Brezillon wrote:
> > 
> >> Clock rates are stored in an unsigned long field, but ->round_rate()
> >> (which returns a rounded rate from a requested one) returns a long
> >> value (errors are reported using negative error codes), which can lead
> >> to long overflow if the clock rate exceed 2Ghz.
> >>
> >> Change ->round_rate() prototype to return 0 or an error code, and pass the
> >> requested rate as a pointer so that it can be adjusted depending on
> >> hardware capabilities.
> > 
> > ...
> > 
> >> diff --git a/Documentation/clk.txt b/Documentation/clk.txt
> >> index 0e4f90a..fca8b7a 100644
> >> --- a/Documentation/clk.txt
> >> +++ b/Documentation/clk.txt
> >> @@ -68,8 +68,8 @@ the operations defined in clk.h:
> >>  		int		(*is_enabled)(struct clk_hw *hw);
> >>  		unsigned long	(*recalc_rate)(struct clk_hw *hw,
> >>  						unsigned long parent_rate);
> >> -		long		(*round_rate)(struct clk_hw *hw,
> >> -						unsigned long rate,
> >> +		int		(*round_rate)(struct clk_hw *hw,
> >> +						unsigned long *rate,
> >>  						unsigned long *parent_rate);
> >>  		long		(*determine_rate)(struct clk_hw *hw,
> >>  						unsigned long rate,
> > 
> > I'd suggest that we should probably go straight to 64-bit rates.  There 
> > are already plenty of clock sources that can generate rates higher than 
> > 4GiHz.
> 
> An alternative would be to introduce to a frequency "base" the default
> could be Hz (for backwards compatibility), but for CPUs we probably only
> care about MHz (or may be kHz) and so 32-bits would still suffice. Even
> if CPUs cared about Hz they could still use Hz, but in that case they
> probably don't care about GHz. Obviously, we don't want to break DT
> compatibility but may be the frequency base could be defined in DT and
> if it is missing then Hz is assumed. Just a thought ...

Yes, but is it really worth the additional complexity. You'll have to
add the unit information anyway, so using an unsigned long for the
value and another field for the unit (an enum ?) is just like using a
64 bit integer.

Best Regards,

Boris

-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com


From heiko at sntech.de  Tue Jun  9 01:03:56 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 09 Jun 2015 10:03:56 +0200
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <4295512.HNTlNbYsVh@diego>

Am Dienstag, 9. Juni 2015, 13:01:16 schrieb Masahiro Yamada:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 

for

>  drivers/pinctrl/pinctrl-rockchip.c            |  4 ++--

Acked-by: Heiko Stuebner <heiko at sntech.de>


From lee at kernel.org  Tue Jun  9 02:52:41 2015
From: lee at kernel.org (Lee Jones)
Date: Tue, 9 Jun 2015 10:52:41 +0100
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20150609095241.GO2982@x1>

On Tue, 09 Jun 2015, Masahiro Yamada wrote:

> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.
> 

>  drivers/pinctrl/bcm/pinctrl-bcm2835.c         |  4 ++--

Acked-by: Lee Jones <lee at kernel.org>


From rjui at broadcom.com  Tue Jun  9 10:55:36 2015
From: rjui at broadcom.com (Ray Jui)
Date: Tue, 9 Jun 2015 10:55:36 -0700
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <55772898.8050601@broadcom.com>

On 6/8/2015 9:01 PM, Masahiro Yamada wrote:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.
> 
> 

>  drivers/pinctrl/bcm/pinctrl-bcm281xx.c        |  4 ++--
>  drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c     |  4 ++--
>  drivers/pinctrl/bcm/pinctrl-cygnus-mux.c      |  4 ++--

Acked-by: Ray Jui <rjui at broadcom.com>


From antoine.tenart at free-electrons.com  Tue Jun  9 11:10:43 2015
From: antoine.tenart at free-electrons.com (Antoine Tenart)
Date: Tue, 9 Jun 2015 20:10:43 +0200
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20150609181043.GA4709@kwain>

Hello,

On Tue, Jun 09, 2015 at 01:01:16PM +0900, Masahiro Yamada wrote:
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.

For,

>  drivers/pinctrl/berlin/berlin.c               |  4 ++--

Acked-by: Antoine Tenart <antoine.tenart at free-electrons.com>

-- 
Antoine T?nart, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com


From jonathanh at nvidia.com  Fri Jun  5 01:46:09 2015
From: jonathanh at nvidia.com (Jon Hunter)
Date: Fri, 5 Jun 2015 09:46:09 +0100
Subject: [PATCH v2 1/2] clk: change clk_ops' ->round_rate() prototype
In-Reply-To: <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
References: <1430407809-31147-1-git-send-email-boris.brezillon@free-electrons.com>
 <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
 <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
Message-ID: <557161D1.3040107@nvidia.com>


On 05/06/15 00:02, Paul Walmsley wrote:
> Hi folks
> 
> just a brief comment on this one:
> 
> On Thu, 30 Apr 2015, Boris Brezillon wrote:
> 
>> Clock rates are stored in an unsigned long field, but ->round_rate()
>> (which returns a rounded rate from a requested one) returns a long
>> value (errors are reported using negative error codes), which can lead
>> to long overflow if the clock rate exceed 2Ghz.
>>
>> Change ->round_rate() prototype to return 0 or an error code, and pass the
>> requested rate as a pointer so that it can be adjusted depending on
>> hardware capabilities.
> 
> ...
> 
>> diff --git a/Documentation/clk.txt b/Documentation/clk.txt
>> index 0e4f90a..fca8b7a 100644
>> --- a/Documentation/clk.txt
>> +++ b/Documentation/clk.txt
>> @@ -68,8 +68,8 @@ the operations defined in clk.h:
>>  		int		(*is_enabled)(struct clk_hw *hw);
>>  		unsigned long	(*recalc_rate)(struct clk_hw *hw,
>>  						unsigned long parent_rate);
>> -		long		(*round_rate)(struct clk_hw *hw,
>> -						unsigned long rate,
>> +		int		(*round_rate)(struct clk_hw *hw,
>> +						unsigned long *rate,
>>  						unsigned long *parent_rate);
>>  		long		(*determine_rate)(struct clk_hw *hw,
>>  						unsigned long rate,
> 
> I'd suggest that we should probably go straight to 64-bit rates.  There 
> are already plenty of clock sources that can generate rates higher than 
> 4GiHz.

An alternative would be to introduce to a frequency "base" the default
could be Hz (for backwards compatibility), but for CPUs we probably only
care about MHz (or may be kHz) and so 32-bits would still suffice. Even
if CPUs cared about Hz they could still use Hz, but in that case they
probably don't care about GHz. Obviously, we don't want to break DT
compatibility but may be the frequency base could be defined in DT and
if it is missing then Hz is assumed. Just a thought ...

Jon


From jonathanh at nvidia.com  Mon Jun  8 01:46:34 2015
From: jonathanh at nvidia.com (Jon Hunter)
Date: Mon, 8 Jun 2015 09:46:34 +0100
Subject: [PATCH v2 1/2] clk: change clk_ops' ->round_rate() prototype
In-Reply-To: <20150605133928.66909901@bbrezillon>
References: <1430407809-31147-1-git-send-email-boris.brezillon@free-electrons.com>
 <1430407809-31147-2-git-send-email-boris.brezillon@free-electrons.com>
 <alpine.DEB.2.02.1506042258530.12316@utopia.booyaka.com>
 <557161D1.3040107@nvidia.com> <20150605133928.66909901@bbrezillon>
Message-ID: <5575566A.4060503@nvidia.com>

Hi Boris,

On 05/06/15 12:39, Boris Brezillon wrote:
> Hi Jon,
> 
> On Fri, 5 Jun 2015 09:46:09 +0100
> Jon Hunter <jonathanh at nvidia.com> wrote:
> 
>>
>> On 05/06/15 00:02, Paul Walmsley wrote:
>>> Hi folks
>>>
>>> just a brief comment on this one:
>>>
>>> On Thu, 30 Apr 2015, Boris Brezillon wrote:
>>>
>>>> Clock rates are stored in an unsigned long field, but ->round_rate()
>>>> (which returns a rounded rate from a requested one) returns a long
>>>> value (errors are reported using negative error codes), which can lead
>>>> to long overflow if the clock rate exceed 2Ghz.
>>>>
>>>> Change ->round_rate() prototype to return 0 or an error code, and pass the
>>>> requested rate as a pointer so that it can be adjusted depending on
>>>> hardware capabilities.
>>>
>>> ...
>>>
>>>> diff --git a/Documentation/clk.txt b/Documentation/clk.txt
>>>> index 0e4f90a..fca8b7a 100644
>>>> --- a/Documentation/clk.txt
>>>> +++ b/Documentation/clk.txt
>>>> @@ -68,8 +68,8 @@ the operations defined in clk.h:
>>>>  		int		(*is_enabled)(struct clk_hw *hw);
>>>>  		unsigned long	(*recalc_rate)(struct clk_hw *hw,
>>>>  						unsigned long parent_rate);
>>>> -		long		(*round_rate)(struct clk_hw *hw,
>>>> -						unsigned long rate,
>>>> +		int		(*round_rate)(struct clk_hw *hw,
>>>> +						unsigned long *rate,
>>>>  						unsigned long *parent_rate);
>>>>  		long		(*determine_rate)(struct clk_hw *hw,
>>>>  						unsigned long rate,
>>>
>>> I'd suggest that we should probably go straight to 64-bit rates.  There 
>>> are already plenty of clock sources that can generate rates higher than 
>>> 4GiHz.
>>
>> An alternative would be to introduce to a frequency "base" the default
>> could be Hz (for backwards compatibility), but for CPUs we probably only
>> care about MHz (or may be kHz) and so 32-bits would still suffice. Even
>> if CPUs cared about Hz they could still use Hz, but in that case they
>> probably don't care about GHz. Obviously, we don't want to break DT
>> compatibility but may be the frequency base could be defined in DT and
>> if it is missing then Hz is assumed. Just a thought ...
> 
> Yes, but is it really worth the additional complexity. You'll have to
> add the unit information anyway, so using an unsigned long for the
> value and another field for the unit (an enum ?) is just like using a
> 64 bit integer.

For a storage perspective, yes it would be the same. However, there are
probably a lot of devices that would not need the extra range, but would
now have to deal with 64-bit types. I have no idea how much overhead
that would be in reality. If the overhead is negligible then a 64-bit
type is definitely the way to go, as I agree it is simpler and cleaner.

Cheers
Jon


From yamada.masahiro at socionext.com  Mon Jun  8 21:01:16 2015
From: yamada.masahiro at socionext.com (Masahiro Yamada)
Date: Tue,  9 Jun 2015 13:01:16 +0900
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
Message-ID: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>

Currently, pinctrl_register() just returns NULL on error, so the
callers can not know the exact reason of the failure.

Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
-ENOMEM on error of pinctrl_register(), although the error code
might be different from the real cause of the error.

This commit reworks pinctrl_register() to return the appropriate
error code and modifies all of the pinctrl drivers to use IS_ERR()
for the error checking and PTR_ERR() for getting the error code.

Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---

This patch is based on linux-pinctrl/devel
(Commit 7164873e7c69d6bab74726debc3b495a86332b1f).

I think I converted all of the pinctrl drivers, but just in case,
I'd like the driver maintainers to check this patch out.


 drivers/pinctrl/bcm/pinctrl-bcm281xx.c        |  4 ++--
 drivers/pinctrl/bcm/pinctrl-bcm2835.c         |  4 ++--
 drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c     |  4 ++--
 drivers/pinctrl/bcm/pinctrl-cygnus-mux.c      |  4 ++--
 drivers/pinctrl/berlin/berlin.c               |  4 ++--
 drivers/pinctrl/core.c                        | 17 ++++++++++-------
 drivers/pinctrl/freescale/pinctrl-imx.c       |  4 ++--
 drivers/pinctrl/freescale/pinctrl-imx1-core.c |  4 ++--
 drivers/pinctrl/freescale/pinctrl-mxs.c       |  4 ++--
 drivers/pinctrl/intel/pinctrl-cherryview.c    |  4 ++--
 drivers/pinctrl/intel/pinctrl-intel.c         |  4 ++--
 drivers/pinctrl/mediatek/pinctrl-mtk-common.c |  4 ++--
 drivers/pinctrl/meson/pinctrl-meson.c         |  4 ++--
 drivers/pinctrl/mvebu/pinctrl-mvebu.c         |  4 ++--
 drivers/pinctrl/nomadik/pinctrl-abx500.c      |  4 ++--
 drivers/pinctrl/nomadik/pinctrl-nomadik.c     |  4 ++--
 drivers/pinctrl/pinctrl-adi2.c                |  4 ++--
 drivers/pinctrl/pinctrl-amd.c                 |  4 ++--
 drivers/pinctrl/pinctrl-as3722.c              |  4 ++--
 drivers/pinctrl/pinctrl-at91.c                |  4 ++--
 drivers/pinctrl/pinctrl-lantiq.c              |  4 ++--
 drivers/pinctrl/pinctrl-lpc18xx.c             |  4 ++--
 drivers/pinctrl/pinctrl-palmas.c              |  4 ++--
 drivers/pinctrl/pinctrl-pistachio.c           |  4 ++--
 drivers/pinctrl/pinctrl-rockchip.c            |  4 ++--
 drivers/pinctrl/pinctrl-single.c              |  4 ++--
 drivers/pinctrl/pinctrl-st.c                  |  4 ++--
 drivers/pinctrl/pinctrl-tb10x.c               |  4 ++--
 drivers/pinctrl/pinctrl-tegra-xusb.c          |  4 ++--
 drivers/pinctrl/pinctrl-tegra.c               |  4 ++--
 drivers/pinctrl/pinctrl-tz1090-pdc.c          |  4 ++--
 drivers/pinctrl/pinctrl-tz1090.c              |  4 ++--
 drivers/pinctrl/pinctrl-u300.c                |  4 ++--
 drivers/pinctrl/pinctrl-zynq.c                |  4 ++--
 drivers/pinctrl/qcom/pinctrl-msm.c            |  4 ++--
 drivers/pinctrl/qcom/pinctrl-spmi-gpio.c      |  4 ++--
 drivers/pinctrl/qcom/pinctrl-spmi-mpp.c       |  4 ++--
 drivers/pinctrl/samsung/pinctrl-exynos5440.c  |  4 ++--
 drivers/pinctrl/samsung/pinctrl-samsung.c     |  4 ++--
 drivers/pinctrl/sh-pfc/pinctrl.c              |  4 ++--
 drivers/pinctrl/sirf/pinctrl-atlas7.c         |  4 ++--
 drivers/pinctrl/sirf/pinctrl-sirf.c           |  4 ++--
 drivers/pinctrl/spear/pinctrl-spear.c         |  4 ++--
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         |  4 ++--
 drivers/pinctrl/vt8500/pinctrl-wmt.c          |  4 ++--
 45 files changed, 98 insertions(+), 95 deletions(-)

diff --git a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
index 9641f1c..c3c692e 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -1425,9 +1425,9 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
 	pctl = pinctrl_register(&bcm281xx_pinctrl_desc,
 				&pdev->dev,
 				pdata);
-	if (!pctl) {
+	if (IS_ERR(pctl)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
-		return -ENODEV;
+		return PTR_ERR(pctl);
 	}
 
 	platform_set_drvdata(pdev, pdata);
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 8d908e3..efcf2a2 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -1036,9 +1036,9 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 	}
 
 	pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
-	if (!pc->pctl_dev) {
+	if (IS_ERR(pc->pctl_dev)) {
 		gpiochip_remove(&pc->gpio_chip);
-		return -EINVAL;
+		return PTR_ERR(pc->pctl_dev);
 	}
 
 	pc->gpio_range = bcm2835_pinctrl_gpio_range;
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
index bde45ba..6af538f 100644
--- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
@@ -748,9 +748,9 @@ static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
 	pctldesc->confops = &cygnus_pconf_ops;
 
 	chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
-	if (!chip->pctl) {
+	if (IS_ERR(chip->pctl)) {
 		dev_err(chip->dev, "unable to register pinctrl device\n");
-		return -EINVAL;
+		return PTR_ERR(chip->pctl);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c
index f9a9283..9728f3d 100644
--- a/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c
+++ b/drivers/pinctrl/bcm/pinctrl-cygnus-mux.c
@@ -989,9 +989,9 @@ static int cygnus_pinmux_probe(struct platform_device *pdev)
 
 	pinctrl->pctl = pinctrl_register(&cygnus_pinctrl_desc, &pdev->dev,
 			pinctrl);
-	if (!pinctrl->pctl) {
+	if (IS_ERR(pinctrl->pctl)) {
 		dev_err(&pdev->dev, "unable to register Cygnus IOMUX pinctrl\n");
-		return -EINVAL;
+		return PTR_ERR(pinctrl->pctl);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
index 7f0b0f9..ddbcd1d 100644
--- a/drivers/pinctrl/berlin/berlin.c
+++ b/drivers/pinctrl/berlin/berlin.c
@@ -320,9 +320,9 @@ int berlin_pinctrl_probe(struct platform_device *pdev,
 	}
 
 	pctrl->pctrl_dev = pinctrl_register(&berlin_pctrl_desc, dev, pctrl);
-	if (!pctrl->pctrl_dev) {
+	if (IS_ERR(pctrl->pctrl_dev)) {
 		dev_err(dev, "failed to register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(pctrl->pctrl_dev);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b01ee72..804d126 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -1706,14 +1706,14 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
 	int ret;
 
 	if (!pctldesc)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 	if (!pctldesc->name)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL);
 	if (pctldev == NULL) {
 		dev_err(dev, "failed to alloc struct pinctrl_dev\n");
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	/* Initialize pin control device struct */
@@ -1726,20 +1726,23 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
 	mutex_init(&pctldev->mutex);
 
 	/* check core ops for sanity */
-	if (pinctrl_check_ops(pctldev)) {
+	ret = pinctrl_check_ops(pctldev);
+	if (ret) {
 		dev_err(dev, "pinctrl ops lacks necessary functions\n");
 		goto out_err;
 	}
 
 	/* If we're implementing pinmuxing, check the ops for sanity */
 	if (pctldesc->pmxops) {
-		if (pinmux_check_ops(pctldev))
+		ret = pinmux_check_ops(pctldev);
+		if (ret)
 			goto out_err;
 	}
 
 	/* If we're implementing pinconfig, check the ops for sanity */
 	if (pctldesc->confops) {
-		if (pinconf_check_ops(pctldev))
+		ret = pinconf_check_ops(pctldev);
+		if (ret)
 			goto out_err;
 	}
 
@@ -1785,7 +1788,7 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
 out_err:
 	mutex_destroy(&pctldev->mutex);
 	kfree(pctldev);
-	return NULL;
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(pinctrl_register);
 
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index e73e1ed..d7b98ba 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -727,9 +727,9 @@ int imx_pinctrl_probe(struct platform_device *pdev,
 	ipctl->dev = info->dev;
 	platform_set_drvdata(pdev, ipctl);
 	ipctl->pctl = pinctrl_register(&imx_pinctrl_desc, &pdev->dev, ipctl);
-	if (!ipctl->pctl) {
+	if (IS_ERR(ipctl->pctl)) {
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(ipctl->pctl);
 	}
 
 	dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
index 5ac59fb..5fd4437 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
@@ -633,9 +633,9 @@ int imx1_pinctrl_core_probe(struct platform_device *pdev,
 	ipctl->dev = info->dev;
 	platform_set_drvdata(pdev, ipctl);
 	ipctl->pctl = pinctrl_register(pctl_desc, &pdev->dev, ipctl);
-	if (!ipctl->pctl) {
+	if (IS_ERR(ipctl->pctl)) {
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(ipctl->pctl);
 	}
 
 	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index 646d5c2..f64eecb 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -540,9 +540,9 @@ int mxs_pinctrl_probe(struct platform_device *pdev,
 	}
 
 	d->pctl = pinctrl_register(&mxs_pinctrl_desc, &pdev->dev, d);
-	if (!d->pctl) {
+	if (IS_ERR(d->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register MXS pinctrl driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(d->pctl);
 		goto err;
 	}
 
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 82f691e..9bed70b 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1489,9 +1489,9 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
 	pctrl->pctldesc.npins = pctrl->community->npins;
 
 	pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl);
-	if (!pctrl->pctldev) {
+	if (IS_ERR(pctrl->pctldev)) {
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pctrl->pctldev);
 	}
 
 	ret = chv_gpio_probe(pctrl, irq);
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 00768e5..f9ee0d6 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -1021,9 +1021,9 @@ int intel_pinctrl_probe(struct platform_device *pdev,
 	pctrl->pctldesc.npins = pctrl->soc->npins;
 
 	pctrl->pctldev = pinctrl_register(&pctrl->pctldesc, &pdev->dev, pctrl);
-	if (!pctrl->pctldev) {
+	if (IS_ERR(pctrl->pctldev)) {
 		dev_err(&pdev->dev, "failed to register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pctrl->pctldev);
 	}
 
 	ret = intel_gpio_probe(pctrl, irq);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index f206a54..35f7b01 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1269,9 +1269,9 @@ int mtk_pctrl_init(struct platform_device *pdev,
 	mtk_pctrl_desc.npins = pctl->devdata->npins;
 	pctl->dev = &pdev->dev;
 	pctl->pctl_dev = pinctrl_register(&mtk_pctrl_desc, &pdev->dev, pctl);
-	if (!pctl->pctl_dev) {
+	if (IS_ERR(pctl->pctl_dev)) {
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(pctl->pctl_dev);
 	}
 
 	pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index edcd140..7b203bf 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -738,9 +738,9 @@ static int meson_pinctrl_probe(struct platform_device *pdev)
 	pc->desc.npins		= pc->data->num_pins;
 
 	pc->pcdev = pinctrl_register(&pc->desc, pc->dev, pc);
-	if (!pc->pcdev) {
+	if (IS_ERR(pc->pcdev)) {
 		dev_err(pc->dev, "can't register pinctrl device");
-		return -EINVAL;
+		return PTR_ERR(pc->pcdev);
 	}
 
 	ret = meson_gpiolib_register(pc);
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index f3b426c..77d2221 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -706,9 +706,9 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 	}
 
 	pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
-	if (!pctl->pctldev) {
+	if (IS_ERR(pctl->pctldev)) {
 		dev_err(&pdev->dev, "unable to register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(pctl->pctldev);
 	}
 
 	dev_info(&pdev->dev, "registered pinctrl driver\n");
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index 15ccafd..557d0f2 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -1235,10 +1235,10 @@ static int abx500_gpio_probe(struct platform_device *pdev)
 	abx500_pinctrl_desc.pins = pct->soc->pins;
 	abx500_pinctrl_desc.npins = pct->soc->npins;
 	pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct);
-	if (!pct->pctldev) {
+	if (IS_ERR(pct->pctldev)) {
 		dev_err(&pdev->dev,
 			"could not register abx500 pinctrl driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(pct->pctldev);
 		goto out_rem_chip;
 	}
 	dev_info(&pdev->dev, "registered pin controller\n");
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
index 2589304..809d884 100644
--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -2029,9 +2029,9 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
 	npct->dev = &pdev->dev;
 
 	npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
-	if (!npct->pctl) {
+	if (IS_ERR(npct->pctl)) {
 		dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(npct->pctl);
 	}
 
 	/* We will handle a range of GPIO pins */
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index 49df903..873433d 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -1070,9 +1070,9 @@ static int adi_pinctrl_probe(struct platform_device *pdev)
 
 	/* Now register the pin controller and all pins it handles */
 	pinctrl->pctl = pinctrl_register(&adi_pinmux_desc, &pdev->dev, pinctrl);
-	if (!pinctrl->pctl) {
+	if (IS_ERR(pinctrl->pctl)) {
 		dev_err(&pdev->dev, "could not register pinctrl ADI2 driver\n");
-		return -EINVAL;
+		return PTR_ERR(pinctrl->pctl);
 	}
 
 	platform_set_drvdata(pdev, pinctrl);
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index e747912..d8e3f7c 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -789,9 +789,9 @@ static int amd_gpio_probe(struct platform_device *pdev)
 	amd_pinctrl_desc.name = dev_name(&pdev->dev);
 	gpio_dev->pctrl = pinctrl_register(&amd_pinctrl_desc,
 					&pdev->dev, gpio_dev);
-	if (!gpio_dev->pctrl) {
+	if (IS_ERR(gpio_dev->pctrl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(gpio_dev->pctrl);
 	}
 
 	ret = gpiochip_add(&gpio_dev->gc);
diff --git a/drivers/pinctrl/pinctrl-as3722.c b/drivers/pinctrl/pinctrl-as3722.c
index db0571f..4747e08 100644
--- a/drivers/pinctrl/pinctrl-as3722.c
+++ b/drivers/pinctrl/pinctrl-as3722.c
@@ -586,9 +586,9 @@ static int as3722_pinctrl_probe(struct platform_device *pdev)
 	as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);
 	as_pci->pctl = pinctrl_register(&as3722_pinctrl_desc,
 					&pdev->dev, as_pci);
-	if (!as_pci->pctl) {
+	if (IS_ERR(as_pci->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(as_pci->pctl);
 	}
 
 	as_pci->gpio_chip = as3722_gpio_chip;
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index d80ade2..a082447 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1238,9 +1238,9 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, info);
 	info->pctl = pinctrl_register(&at91_pinctrl_desc, &pdev->dev, info);
 
-	if (!info->pctl) {
+	if (IS_ERR(info->pctl)) {
 		dev_err(&pdev->dev, "could not register AT91 pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(info->pctl);
 	}
 
 	/* We will handle a range of GPIO pins */
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index 296e5b3..fc38a85 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -337,9 +337,9 @@ int ltq_pinctrl_register(struct platform_device *pdev,
 	info->dev = &pdev->dev;
 
 	info->pctrl = pinctrl_register(desc, &pdev->dev, info);
-	if (!info->pctrl) {
+	if (IS_ERR(info->pctrl)) {
 		dev_err(&pdev->dev, "failed to register LTQ pinmux driver\n");
-		return -EINVAL;
+		return PTR_ERR(info->pctrl);
 	}
 	platform_set_drvdata(pdev, info);
 	return 0;
diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c
index a8bc1ad..ef0b697 100644
--- a/drivers/pinctrl/pinctrl-lpc18xx.c
+++ b/drivers/pinctrl/pinctrl-lpc18xx.c
@@ -1180,10 +1180,10 @@ static int lpc18xx_scu_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, scu);
 
 	scu->pctl = pinctrl_register(&lpc18xx_scu_desc, &pdev->dev, scu);
-	if (!scu->pctl) {
+	if (IS_ERR(scu->pctl)) {
 		dev_err(&pdev->dev, "Could not register pinctrl driver\n");
 		clk_disable_unprepare(scu->clk);
-		return -EINVAL;
+		return PTR_ERR(scu->pctl);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/pinctrl-palmas.c b/drivers/pinctrl/pinctrl-palmas.c
index 2631df0..f7e1680 100644
--- a/drivers/pinctrl/pinctrl-palmas.c
+++ b/drivers/pinctrl/pinctrl-palmas.c
@@ -1044,9 +1044,9 @@ static int palmas_pinctrl_probe(struct platform_device *pdev)
 	palmas_pinctrl_desc.pins = palmas_pins_desc;
 	palmas_pinctrl_desc.npins = ARRAY_SIZE(palmas_pins_desc);
 	pci->pctl = pinctrl_register(&palmas_pinctrl_desc, &pdev->dev, pci);
-	if (!pci->pctl) {
+	if (IS_ERR(pci->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pci->pctl);
 	}
 	return 0;
 }
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index 079ce8b..63100be 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1474,9 +1474,9 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
 
 	pctl->pctldev = pinctrl_register(&pistachio_pinctrl_desc, &pdev->dev,
 					 pctl);
-	if (!pctl->pctldev) {
+	if (IS_ERR(pctl->pctldev)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl device\n");
-		return -EINVAL;
+		return PTR_ERR(pctl->pctldev);
 	}
 
 	ret = pistachio_gpio_register(pctl);
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index dee7d5f..6e7643f 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -1274,9 +1274,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
 		return ret;
 
 	info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info);
-	if (!info->pctl_dev) {
+	if (IS_ERR(info->pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(info->pctl_dev);
 	}
 
 	for (bank = 0; bank < info->ctrl->nr_banks; ++bank) {
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 968e352..b2de09d 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1921,9 +1921,9 @@ static int pcs_probe(struct platform_device *pdev)
 		goto free;
 
 	pcs->pctl = pinctrl_register(&pcs->desc, pcs->dev, pcs);
-	if (!pcs->pctl) {
+	if (IS_ERR(pcs->pctl)) {
 		dev_err(pcs->dev, "could not register single pinctrl driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(pcs->pctl);
 		goto free;
 	}
 
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 65bf73b..d34ac87 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -1737,9 +1737,9 @@ static int st_pctl_probe(struct platform_device *pdev)
 	pctl_desc->name		= dev_name(&pdev->dev);
 
 	info->pctl = pinctrl_register(pctl_desc, &pdev->dev, info);
-	if (!info->pctl) {
+	if (IS_ERR(info->pctl)) {
 		dev_err(&pdev->dev, "Failed pinctrl registration\n");
-		return -EINVAL;
+		return PTR_ERR(info->pctl);
 	}
 
 	for (i = 0; i < info->nbanks; i++)
diff --git a/drivers/pinctrl/pinctrl-tb10x.c b/drivers/pinctrl/pinctrl-tb10x.c
index 160a1f5..6546b9b 100644
--- a/drivers/pinctrl/pinctrl-tb10x.c
+++ b/drivers/pinctrl/pinctrl-tb10x.c
@@ -807,9 +807,9 @@ static int tb10x_pinctrl_probe(struct platform_device *pdev)
 	}
 
 	state->pctl = pinctrl_register(&tb10x_pindesc, dev, state);
-	if (!state->pctl) {
+	if (IS_ERR(state->pctl)) {
 		dev_err(dev, "could not register TB10x pin driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(state->pctl);
 		goto fail;
 	}
 
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index 6a6eebf..2651d04 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -922,9 +922,9 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	padctl->desc.owner = THIS_MODULE;
 
 	padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
-	if (!padctl->pinctrl) {
+	if (IS_ERR(padctl->pinctrl)) {
 		dev_err(&pdev->dev, "failed to register pincontrol\n");
-		err = -ENODEV;
+		err = PTR_ERR(padctl->pinctrl);
 		goto reset;
 	}
 
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 4c95c20..0f982b8 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -703,9 +703,9 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
 	}
 
 	pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx);
-	if (!pmx->pctl) {
+	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pmx->pctl);
 	}
 
 	pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
diff --git a/drivers/pinctrl/pinctrl-tz1090-pdc.c b/drivers/pinctrl/pinctrl-tz1090-pdc.c
index 8a8911b..c349911 100644
--- a/drivers/pinctrl/pinctrl-tz1090-pdc.c
+++ b/drivers/pinctrl/pinctrl-tz1090-pdc.c
@@ -948,9 +948,9 @@ static int tz1090_pdc_pinctrl_probe(struct platform_device *pdev)
 		return PTR_ERR(pmx->regs);
 
 	pmx->pctl = pinctrl_register(&tz1090_pdc_pinctrl_desc, &pdev->dev, pmx);
-	if (!pmx->pctl) {
+	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pmx->pctl);
 	}
 
 	platform_set_drvdata(pdev, pmx);
diff --git a/drivers/pinctrl/pinctrl-tz1090.c b/drivers/pinctrl/pinctrl-tz1090.c
index fc5594a5..6d07a2f 100644
--- a/drivers/pinctrl/pinctrl-tz1090.c
+++ b/drivers/pinctrl/pinctrl-tz1090.c
@@ -1963,9 +1963,9 @@ static int tz1090_pinctrl_probe(struct platform_device *pdev)
 		return PTR_ERR(pmx->regs);
 
 	pmx->pctl = pinctrl_register(&tz1090_pinctrl_desc, &pdev->dev, pmx);
-	if (!pmx->pctl) {
+	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pmx->pctl);
 	}
 
 	platform_set_drvdata(pdev, pmx);
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index f931e65..c076021 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -1068,9 +1068,9 @@ static int u300_pmx_probe(struct platform_device *pdev)
 		return PTR_ERR(upmx->virtbase);
 
 	upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
-	if (!upmx->pctl) {
+	if (IS_ERR(upmx->pctl)) {
 		dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
-		return -EINVAL;
+		return PTR_ERR(upmx->pctl);
 	}
 
 	platform_set_drvdata(pdev, upmx);
diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c
index 40b2aff..7ce23b6 100644
--- a/drivers/pinctrl/pinctrl-zynq.c
+++ b/drivers/pinctrl/pinctrl-zynq.c
@@ -1196,8 +1196,8 @@ static int zynq_pinctrl_probe(struct platform_device *pdev)
 	pctrl->nfuncs = ARRAY_SIZE(zynq_pmux_functions);
 
 	pctrl->pctrl = pinctrl_register(&zynq_desc, &pdev->dev, pctrl);
-	if (!pctrl->pctrl)
-		return -ENOMEM;
+	if (IS_ERR(pctrl->pctrl))
+		return PTR_ERR(pctrl->pctrl);
 
 	platform_set_drvdata(pdev, pctrl);
 
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index f3d800f..e457d52 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -906,9 +906,9 @@ int msm_pinctrl_probe(struct platform_device *pdev,
 	msm_pinctrl_desc.pins = pctrl->soc->pins;
 	msm_pinctrl_desc.npins = pctrl->soc->npins;
 	pctrl->pctrl = pinctrl_register(&msm_pinctrl_desc, &pdev->dev, pctrl);
-	if (!pctrl->pctrl) {
+	if (IS_ERR(pctrl->pctrl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pctrl->pctrl);
 	}
 
 	ret = msm_gpio_init(pctrl);
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index b2d2221..f92f229 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -776,8 +776,8 @@ static int pmic_gpio_probe(struct platform_device *pdev)
 	state->chip.can_sleep = false;
 
 	state->ctrl = pinctrl_register(pctrldesc, dev, state);
-	if (!state->ctrl)
-		return -ENODEV;
+	if (IS_ERR(state->ctrl))
+		return PTR_ERR(state->ctrl);
 
 	ret = gpiochip_add(&state->chip);
 	if (ret) {
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
index 8f36c5f..cd7ca11 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
@@ -890,8 +890,8 @@ static int pmic_mpp_probe(struct platform_device *pdev)
 	state->chip.can_sleep = false;
 
 	state->ctrl = pinctrl_register(pctrldesc, dev, state);
-	if (!state->ctrl)
-		return -ENODEV;
+	if (IS_ERR(state->ctrl))
+		return PTR_ERR(state->ctrl);
 
 	ret = gpiochip_add(&state->chip);
 	if (ret) {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 86192be..f5619fb 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -822,9 +822,9 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
 		return ret;
 
 	pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, priv);
-	if (!pctl_dev) {
+	if (IS_ERR(pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(pctl_dev);
 	}
 
 	grange.name = "exynos5440-pctrl-gpio-range";
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 0fd20c5..3dd5a3b 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -873,9 +873,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
 		return ret;
 
 	drvdata->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, drvdata);
-	if (!drvdata->pctl_dev) {
+	if (IS_ERR(drvdata->pctl_dev)) {
 		dev_err(&pdev->dev, "could not register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(drvdata->pctl_dev);
 	}
 
 	for (bank = 0; bank < drvdata->nr_banks; ++bank) {
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 072e7c6..ff67896 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -625,8 +625,8 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
 	pmx->pctl_desc.npins = pfc->info->nr_pins;
 
 	pmx->pctl = pinctrl_register(&pmx->pctl_desc, pfc->dev, pmx);
-	if (pmx->pctl == NULL)
-		return -EINVAL;
+	if (IS_ERR(pmx->pctl))
+		return PTR_ERR(pmx->pctl);
 
 	return 0;
 }
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
index c2ced3f..9384e0a 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
@@ -4079,9 +4079,9 @@ static int atlas7_pinmux_probe(struct platform_device *pdev)
 
 	/* Now register the pin controller and all pins it handles */
 	pmx->pctl = pinctrl_register(&pmx->pctl_desc, &pdev->dev, pmx);
-	if (!pmx->pctl) {
+	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "could not register atlas7 pinmux driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(pmx->pctl);
 		goto unmap_io;
 	}
 
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index e2efbba..8ba26e4 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -310,9 +310,9 @@ static int sirfsoc_pinmux_probe(struct platform_device *pdev)
 
 	/* Now register the pin controller and all pins it handles */
 	spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
-	if (!spmx->pmx) {
+	if (IS_ERR(spmx->pmx)) {
 		dev_err(&pdev->dev, "could not register SIRFSOC pinmux driver\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(spmx->pmx);
 		goto out_no_pmx;
 	}
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index abdb05a..f87a5ea 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -396,9 +396,9 @@ int spear_pinctrl_probe(struct platform_device *pdev,
 	spear_pinctrl_desc.npins = machdata->npins;
 
 	pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx);
-	if (!pmx->pctl) {
+	if (IS_ERR(pmx->pctl)) {
 		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
-		return -ENODEV;
+		return PTR_ERR(pmx->pctl);
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index f8e171b..d7857c7 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -911,9 +911,9 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
 
 	pctl->pctl_dev = pinctrl_register(pctrl_desc,
 					  &pdev->dev, pctl);
-	if (!pctl->pctl_dev) {
+	if (IS_ERR(pctl->pctl_dev)) {
 		dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
-		return -EINVAL;
+		return PTR_ERR(pctl->pctl_dev);
 	}
 
 	pctl->chip = devm_kzalloc(&pdev->dev, sizeof(*pctl->chip), GFP_KERNEL);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index d055d63..c15316b 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -594,9 +594,9 @@ int wmt_pinctrl_probe(struct platform_device *pdev,
 	data->dev = &pdev->dev;
 
 	data->pctl_dev = pinctrl_register(&wmt_desc, &pdev->dev, data);
-	if (!data->pctl_dev) {
+	if (IS_ERR(data->pctl_dev)) {
 		dev_err(&pdev->dev, "Failed to register pinctrl\n");
-		return -EINVAL;
+		return PTR_ERR(data->pctl_dev);
 	}
 
 	err = gpiochip_add(&data->gpio_chip);
-- 
1.9.1



From patrice.chotard at st.com  Tue Jun  9 00:29:59 2015
From: patrice.chotard at st.com (Patrice Chotard)
Date: Tue, 9 Jun 2015 09:29:59 +0200
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <557695F7.6050907@st.com>

Hi Masahiro

On 06/09/2015 06:01 AM, Masahiro Yamada wrote:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
>
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
>
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
>
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
>
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.
>
>
>   drivers/pinctrl/bcm/pinctrl-bcm281xx.c        |  4 ++--
>   drivers/pinctrl/bcm/pinctrl-bcm2835.c         |  4 ++--
>   drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c     |  4 ++--
>   drivers/pinctrl/bcm/pinctrl-cygnus-mux.c      |  4 ++--
>   drivers/pinctrl/berlin/berlin.c               |  4 ++--
>   drivers/pinctrl/core.c                        | 17 ++++++++++-------
>   drivers/pinctrl/freescale/pinctrl-imx.c       |  4 ++--
>   drivers/pinctrl/freescale/pinctrl-imx1-core.c |  4 ++--
>   drivers/pinctrl/freescale/pinctrl-mxs.c       |  4 ++--
>   drivers/pinctrl/intel/pinctrl-cherryview.c    |  4 ++--
>   drivers/pinctrl/intel/pinctrl-intel.c         |  4 ++--
>   drivers/pinctrl/mediatek/pinctrl-mtk-common.c |  4 ++--
>   drivers/pinctrl/meson/pinctrl-meson.c         |  4 ++--
>   drivers/pinctrl/mvebu/pinctrl-mvebu.c         |  4 ++--
>   drivers/pinctrl/nomadik/pinctrl-abx500.c      |  4 ++--
>   drivers/pinctrl/nomadik/pinctrl-nomadik.c     |  4 ++--
>   drivers/pinctrl/pinctrl-adi2.c                |  4 ++--
>   drivers/pinctrl/pinctrl-amd.c                 |  4 ++--
>   drivers/pinctrl/pinctrl-as3722.c              |  4 ++--
>   drivers/pinctrl/pinctrl-at91.c                |  4 ++--
>   drivers/pinctrl/pinctrl-lantiq.c              |  4 ++--
>   drivers/pinctrl/pinctrl-lpc18xx.c             |  4 ++--
>   drivers/pinctrl/pinctrl-palmas.c              |  4 ++--
>   drivers/pinctrl/pinctrl-pistachio.c           |  4 ++--
>   drivers/pinctrl/pinctrl-rockchip.c            |  4 ++--
>   drivers/pinctrl/pinctrl-single.c              |  4 ++--
>   drivers/pinctrl/pinctrl-st.c                  |  4 ++--
>   drivers/pinctrl/pinctrl-tb10x.c               |  4 ++--
>   drivers/pinctrl/pinctrl-tegra-xusb.c          |  4 ++--
>   drivers/pinctrl/pinctrl-tegra.c               |  4 ++--
>   drivers/pinctrl/pinctrl-tz1090-pdc.c          |  4 ++--
>   drivers/pinctrl/pinctrl-tz1090.c              |  4 ++--
>   drivers/pinctrl/pinctrl-u300.c                |  4 ++--
>   drivers/pinctrl/pinctrl-zynq.c                |  4 ++--
>   drivers/pinctrl/qcom/pinctrl-msm.c            |  4 ++--
>   drivers/pinctrl/qcom/pinctrl-spmi-gpio.c      |  4 ++--
>   drivers/pinctrl/qcom/pinctrl-spmi-mpp.c       |  4 ++--
>   drivers/pinctrl/samsung/pinctrl-exynos5440.c  |  4 ++--
>   drivers/pinctrl/samsung/pinctrl-samsung.c     |  4 ++--
>   drivers/pinctrl/sh-pfc/pinctrl.c              |  4 ++--
>   drivers/pinctrl/sirf/pinctrl-atlas7.c         |  4 ++--
>   drivers/pinctrl/sirf/pinctrl-sirf.c           |  4 ++--
>   drivers/pinctrl/spear/pinctrl-spear.c         |  4 ++--
>   drivers/pinctrl/sunxi/pinctrl-sunxi.c         |  4 ++--
>   drivers/pinctrl/vt8500/pinctrl-wmt.c          |  4 ++--
>   45 files changed, 98 insertions(+), 95 deletions(-)
>
> <snip>


for

  drivers/pinctrl/nomadik/pinctrl-abx500.c      |  4 ++--

and

  drivers/pinctrl/pinctrl-st.c                  |  4 ++--

Acked-by: Patrice Chotard <patrice.chotard at st.com>

Thanks

Patrice



From thierry.reding at gmail.com  Tue Jun  9 01:00:45 2015
From: thierry.reding at gmail.com (Thierry Reding)
Date: Tue, 9 Jun 2015 10:00:45 +0200
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20150609080041.GB28198@ulmo>

On Tue, Jun 09, 2015 at 01:01:16PM +0900, Masahiro Yamada wrote:
[...]
>  drivers/pinctrl/pinctrl-tegra-xusb.c          |  4 ++--
>  drivers/pinctrl/pinctrl-tegra.c               |  4 ++--

Acked-by: Thierry Reding <treding at nvidia.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-rockchip/attachments/20150609/e64f93b7/attachment-0001.sig>

From soren.brinkmann at xilinx.com  Tue Jun  9 08:48:21 2015
From: soren.brinkmann at xilinx.com (=?utf-8?B?U8O2cmVu?= Brinkmann)
Date: Tue, 9 Jun 2015 08:48:21 -0700
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <20150609154821.GW8863@xsjsorenbubuntu>

On Tue, 2015-06-09 at 01:01PM +0900, Masahiro Yamada wrote:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.
> 

For
>  drivers/pinctrl/pinctrl-zynq.c                |  4 ++--

Acked-by: S?ren Brinkmann <soren.brinkmann at xilinx.com>

	S?ren


From laurent.pinchart at ideasonboard.com  Tue Jun  9 09:54:08 2015
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Tue, 09 Jun 2015 19:54:08 +0300
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1628402.KJhrHXyhsd@avalon>

Hello Yamada-san,

Thank you for the patch.

On Tuesday 09 June 2015 13:01:16 Masahiro Yamada wrote:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.

[snip]

For

>  drivers/pinctrl/core.c                        | 17 ++++++++++-------
>  drivers/pinctrl/sh-pfc/pinctrl.c              |  4 ++--

Acked-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

-- 
Regards,

Laurent Pinchart



From hongzhou.yang at mediatek.com  Tue Jun  9 12:08:07 2015
From: hongzhou.yang at mediatek.com (Hongzhou Yang)
Date: Tue, 9 Jun 2015 12:08:07 -0700
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <1433876887.40937.2.camel@mussux00.eus.mediatek.inc>

On Tue, 2015-06-09 at 13:01 +0900, Masahiro Yamada wrote:
> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
> 
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
> 
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
> 
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
> ---
> 
> This patch is based on linux-pinctrl/devel
> (Commit 7164873e7c69d6bab74726debc3b495a86332b1f).
> 
> I think I converted all of the pinctrl drivers, but just in case,
> I'd like the driver maintainers to check this patch out.
> 

For

>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c |  4 ++--

Acked-by: Hongzhou Yang <hongzhou.yang at mediatek.com>

Thanks
Hongzhou



From Wei.Chen at csr.com  Tue Jun  9 18:40:09 2015
From: Wei.Chen at csr.com (Wei Chen)
Date: Wed, 10 Jun 2015 01:40:09 +0000
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <B76E48C3750A2544864630797F6798A4263AE2D3@SHAASIEXM01.ASIA.ROOT.PRI>

Hi,

On Tue, Jun 09, 2015 at 01:01:16PM +0900, Masahiro Yamada wrote:
> 
> I think I converted all of the pinctrl drivers, but just in case, I'd 
> like the driver maintainers to check this patch out.

For,

>  drivers/pinctrl/sirf/pinctrl-atlas7.c         |  4 ++--

Acked-by: Wei Chen <Wei.Chen at csr.com>

Regards.
Wei Chen.




Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Keep up to date with CSR on our technical blog, www.csr.com/blog, CSR people blog, www.csr.com/people, YouTube, www.youtube.com/user/CSRplc, Facebook, www.facebook.com/pages/CSR/191038434253534, or follow us on Twitter at www.twitter.com/CSR_plc.
You can now access the wide range of products powered by aptX at www.aptx.com

From jiang.liu at linux.intel.com  Wed Jun 10 01:23:04 2015
From: jiang.liu at linux.intel.com (Jiang Liu)
Date: Wed, 10 Jun 2015 16:23:04 +0800
Subject: [RFT v2 44/48] genirq, pinctrl: Kill the first parameter 'irq'
 of irq_flow_handler_t
In-Reply-To: <CACRpkdZDxAPxLAuvD5cD7XLLKM45aS7_oAcPhKBM1ewmUn9+BA@mail.gmail.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>	<1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
 <CACRpkdZDxAPxLAuvD5cD7XLLKM45aS7_oAcPhKBM1ewmUn9+BA@mail.gmail.com>
Message-ID: <5577F3E8.1070704@linux.intel.com>

On 2015/6/10 16:12, Linus Walleij wrote:
> On Thu, Jun 4, 2015 at 6:13 AM, Jiang Liu <jiang.liu at linux.intel.com> wrote:
> 
>> Now most IRQ flow handlers make no use of the first parameter 'irq'.
>> And for those who do make use of 'irq', we could easily get the irq
>> number through irq_desc->irq_data->irq. So kill the first parameter
>> 'irq' of irq_flow_handler_t.
>>
>> To ease review, I have split the changes into several parts, though
>> they should be merge as one to support bisecting.
>>
>> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> 
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> 
> Assume that I can't apply this directly. If I can during
> next kernel cycle, push me.
Thanks Linus!
This patch set need to be handled as an integral part, otherwise
it will cause compilation issues.


From linus.walleij at linaro.org  Wed Jun 10 01:12:37 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 10 Jun 2015 10:12:37 +0200
Subject: [RFT v2 44/48] genirq,
 pinctrl: Kill the first parameter 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CACRpkdZDxAPxLAuvD5cD7XLLKM45aS7_oAcPhKBM1ewmUn9+BA@mail.gmail.com>

On Thu, Jun 4, 2015 at 6:13 AM, Jiang Liu <jiang.liu at linux.intel.com> wrote:

> Now most IRQ flow handlers make no use of the first parameter 'irq'.
> And for those who do make use of 'irq', we could easily get the irq
> number through irq_desc->irq_data->irq. So kill the first parameter
> 'irq' of irq_flow_handler_t.
>
> To ease review, I have split the changes into several parts, though
> they should be merge as one to support bisecting.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Assume that I can't apply this directly. If I can during
next kernel cycle, push me.

Yours,
Linus Walleij


From heiko at sntech.de  Wed Jun 10 01:39:44 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Wed, 10 Jun 2015 10:39:44 +0200
Subject: [RFT v2 06/48] pinctrl: Use irq_desc_get_xxx() to avoid redundant
 lookup of irq_desc
In-Reply-To: <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <11293365.dyj0hfgNSb@diego>

Am Donnerstag, 4. Juni 2015, 12:13:16 schrieb Jiang Liu:
> Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc while we
> already have a pointer to corresponding irq_desc.
> 
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> ---
>  drivers/pinctrl/pinctrl-rockchip.c            |    4 ++--


For Rockchip
Acked-by: Heiko Stuebner <heiko at sntech.de>



From heiko at sntech.de  Wed Jun 10 01:40:09 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Wed, 10 Jun 2015 10:40:09 +0200
Subject: [RFT v2 44/48] genirq,
 pinctrl: Kill the first parameter 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <29876063.DDhUqa5fWz@diego>

Am Donnerstag, 4. Juni 2015, 12:13:54 schrieb Jiang Liu:
> Now most IRQ flow handlers make no use of the first parameter 'irq'.
> And for those who do make use of 'irq', we could easily get the irq
> number through irq_desc->irq_data->irq. So kill the first parameter
> 'irq' of irq_flow_handler_t.
> 
> To ease review, I have split the changes into several parts, though
> they should be merge as one to support bisecting.
> 
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> ---

>  drivers/pinctrl/pinctrl-rockchip.c            |    2 +-

For Rockchip
Acked-by: Heiko Stuebner <heiko at sntech.de>



From matthias.bgg at gmail.com  Wed Jun 10 03:29:42 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Wed, 10 Jun 2015 12:29:42 +0200
Subject: [RFT v2 06/48] pinctrl: Use irq_desc_get_xxx() to avoid redundant
 lookup of irq_desc
In-Reply-To: <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-7-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CABuKBeLs21NZ_uTUJ=P6TwX-jAiCaJO--ZnV7O2MZy-TfV6sNw@mail.gmail.com>

2015-06-04 6:13 GMT+02:00 Jiang Liu <jiang.liu at linux.intel.com>:
> Use irq_desc_get_xxx() to avoid redundant lookup of irq_desc while we
> already have a pointer to corresponding irq_desc.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>
> ---
[...]
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    4 ++--

For the changes in pinctrl-mtk-common.c:

Acked-by: Matthias Brugger <matthias.brugger at gmail.com>


From matthias.bgg at gmail.com  Wed Jun 10 03:31:27 2015
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Wed, 10 Jun 2015 12:31:27 +0200
Subject: [RFT v2 44/48] genirq,
 pinctrl: Kill the first parameter 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-45-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CABuKBeKF_q6HEGFdeBzMbd+Zo009mRtmUiDRPebV_nd04j5tTQ@mail.gmail.com>

2015-06-04 6:13 GMT+02:00 Jiang Liu <jiang.liu at linux.intel.com>:
> Now most IRQ flow handlers make no use of the first parameter 'irq'.
> And for those who do make use of 'irq', we could easily get the irq
> number through irq_desc->irq_data->irq. So kill the first parameter
> 'irq' of irq_flow_handler_t.
>
> To ease review, I have split the changes into several parts, though
> they should be merge as one to support bisecting.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>
> ---
[...]
>  drivers/pinctrl/mediatek/pinctrl-mtk-common.c |    2 +-

For Mediatek:
Acked-by: Matthias Brugger <matthias.bgg at gmail.com>


From linus.walleij at linaro.org  Wed Jun 10 05:52:30 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 10 Jun 2015 14:52:30 +0200
Subject: [PATCH] pinctrl: make pinctrl_register() return proper error code
In-Reply-To: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
References: <1433822476-26531-1-git-send-email-yamada.masahiro@socionext.com>
Message-ID: <CACRpkdbuOsRK9_AeKe-eQ-uCUqT1212NFe4OKLdzc+QoBxN1Bw@mail.gmail.com>

On Tue, Jun 9, 2015 at 6:01 AM, Masahiro Yamada
<yamada.masahiro at socionext.com> wrote:

> Currently, pinctrl_register() just returns NULL on error, so the
> callers can not know the exact reason of the failure.
>
> Some of the pinctrl drivers return -EINVAL, some -ENODEV, and some
> -ENOMEM on error of pinctrl_register(), although the error code
> might be different from the real cause of the error.
>
> This commit reworks pinctrl_register() to return the appropriate
> error code and modifies all of the pinctrl drivers to use IS_ERR()
> for the error checking and PTR_ERR() for getting the error code.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>

Patch applied, with the ACK-storm.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed Jun 10 06:14:06 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 10 Jun 2015 15:14:06 +0200
Subject: [RFT v2 34/48] pinctrl: Prepare for killing the first parameter
 'irq' of irq_flow_handler_t
In-Reply-To: <1433391238-19471-35-git-send-email-jiang.liu@linux.intel.com>
References: <1433391238-19471-1-git-send-email-jiang.liu@linux.intel.com>
 <1433391238-19471-35-git-send-email-jiang.liu@linux.intel.com>
Message-ID: <CACRpkdZUD3VQkrT1JReiKvM1SZf_nJiN-=JNZoyMJjK0MGefuQ@mail.gmail.com>

On Thu, Jun 4, 2015 at 6:13 AM, Jiang Liu <jiang.liu at linux.intel.com> wrote:

> Change irq flow handler to prepare for killing the first parameter 'irq'
> of irq_flow_handler_t.
>
> Signed-off-by: Jiang Liu <jiang.liu at linux.intel.com>

Acked-by: Linus Walleij <linus.walleij at linaro.org>

Yours,
Linus Walleij


From romain.perier at gmail.com  Thu Jun 11 06:43:52 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Thu, 11 Jun 2015 15:43:52 +0200
Subject: [PATCH 1/2] dt-bindings: add vendor prefix for Netxeon Technology
In-Reply-To: <19362183.0Io0nOHtsp@phil>
References: <19362183.0Io0nOHtsp@phil>
Message-ID: <CABgxDoJWJAguvoPLr1dwBZj4TaJFZFXmyL56f5jNPCwc7d4Qqw@mail.gmail.com>

Signed-off-by: Romain Perier <romain.perier at gmail.com>

for the whole serie

2015-05-26 21:49 GMT+02:00 Heiko Stuebner <heiko at sntech.de>:
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 8033919..1de2dfd 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -134,6 +134,7 @@ national    National Semiconductor
>  neonode                Neonode Inc.
>  netgear        NETGEAR
>  netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
> +netxeon                Shenzhen Netxeon Technology CO., LTD
>  newhaven       Newhaven Display International
>  nintendo       Nintendo
>  nokia  Nokia
> --
> 2.1.4
>
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


From heiko at sntech.de  Thu Jun 11 08:38:11 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 11 Jun 2015 17:38:11 +0200
Subject: [PATCH 1/2] dt-bindings: add vendor prefix for Netxeon Technology
In-Reply-To: <CABgxDoJWJAguvoPLr1dwBZj4TaJFZFXmyL56f5jNPCwc7d4Qqw@mail.gmail.com>
References: <19362183.0Io0nOHtsp@phil>
 <CABgxDoJWJAguvoPLr1dwBZj4TaJFZFXmyL56f5jNPCwc7d4Qqw@mail.gmail.com>
Message-ID: <2658445.Ovirmp61rs@diego>

Am Donnerstag, 11. Juni 2015, 15:43:52 schrieb Romain Perier:
> Signed-off-by: Romain Perier <romain.perier at gmail.com>

I think the appropriate tag would've been Reviewed-by ;-)


Heiko

> 
> for the whole serie
> 
> 2015-05-26 21:49 GMT+02:00 Heiko Stuebner <heiko at sntech.de>:
> > Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> > ---
> > 
> >  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > b/Documentation/devicetree/bindings/vendor-prefixes.txt index
> > 8033919..1de2dfd 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> > @@ -134,6 +134,7 @@ national    National Semiconductor
> > 
> >  neonode                Neonode Inc.
> >  netgear        NETGEAR
> >  netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
> > 
> > +netxeon                Shenzhen Netxeon Technology CO., LTD
> > 
> >  newhaven       Newhaven Display International
> >  nintendo       Nintendo
> >  nokia  Nokia
> > 
> > --
> > 2.1.4
> > 
> > 
> > 
> > _______________________________________________
> > Linux-rockchip mailing list
> > Linux-rockchip at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-rockchip



From robherring2 at gmail.com  Thu Jun 11 19:55:17 2015
From: robherring2 at gmail.com (Rob Herring)
Date: Thu, 11 Jun 2015 21:55:17 -0500
Subject: [PATCH 1/2] dt-bindings: add vendor prefix for Netxeon Technology
In-Reply-To: <19362183.0Io0nOHtsp@phil>
References: <19362183.0Io0nOHtsp@phil>
Message-ID: <CAL_Jsq+ewJt0Qkqosioqp-KgPwku_h-9poOVjF8N6d7YJscpjA@mail.gmail.com>

On Tue, May 26, 2015 at 2:49 PM, Heiko Stuebner <heiko at sntech.de> wrote:
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +

Acked-by: Rob Herring <robh at kernel.org>

>  1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
> index 8033919..1de2dfd 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -134,6 +134,7 @@ national    National Semiconductor
>  neonode                Neonode Inc.
>  netgear        NETGEAR
>  netlogic       Broadcom Corporation (formerly NetLogic Microsystems)
> +netxeon                Shenzhen Netxeon Technology CO., LTD
>  newhaven       Newhaven Display International
>  nintendo       Nintendo
>  nokia  Nokia
> --
> 2.1.4
>
>


From caesar.upstream at gmail.com  Thu Jun 11 22:11:01 2015
From: caesar.upstream at gmail.com (Caesar Wang)
Date: Fri, 12 Jun 2015 13:11:01 +0800
Subject: [PATCH v14 0/3] ARM: rk3288: Add PM Domain support
In-Reply-To: <7h383lzaqt.fsf@deeprootsystems.com>
References: <1429862868-14218-1-git-send-email-wxt@rock-chips.com>	<3550912.kR0pejLP0h@diego>
 <7h383lzaqt.fsf@deeprootsystems.com>
Message-ID: <557A69E5.5080701@gmail.com>

Hi Kevin, Heiko

Thanks for your comments.
Sorry for delay reply.

? 2015?04?28? 02:28, Kevin Hilman ??:
> Heiko St?bner <heiko at sntech.de> writes:
>
>> Am Freitag, 24. April 2015, 16:07:45 schrieb Caesar Wang:
>>>      Add power domain drivers based on generic power domain for
>>> Rockchip platform, and support RK3288.
>>>
>>>      Verified on url =
>>>      https://chromium.googlesource.com/chromiumos/third_party/kernel.
>>>
>>>      At the moment,there are mass of products are using the driver.
>>> I believe the driver can happy work for next kernel.
>> I've taken a look at the driver and here are some global remarks:
>>
>> (1) You provide dt-bindings/power-domain/rk3288.h in patch 3. This breaks
>> bisectability, as the driver itself in patch 2 also includes the header and
>> would thus fail to compile if the later patch 3 is missing.
>> Ideally I think the header addition should be a separate patch itself, so that
>> we can possibly share it between driver and dts branches.
>> So 1: binding doc, 2: binding-header, 3: driver, 4: dts-changes.
OK, done.

>>
>> (2) The dts-changes in patch 3 should also add any necessary power-domain
>> assignment on devices if they're still missing, so that we don't introduce
>> regressions. In my case my work-in-progress edp died because the powerdomain
>> was turned off automatically it seems.
OK, I will list that devices.
At the moment, I don't find the EDP driver for rockchip. (I think the 
EDP driver hasn't a upstream).

Anyway, I will test it on 
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-3.14,
Meanwhile work on next-kernel.


>>
>> (3) more like wondering @Kevin or so, is there some more generic place for a
>> power-domain driver nowadays?
> I think the preference has been to put these under drivers/soc/<vendor> for now,
> so they can shared across arm32 and arm64.
>

Interesting. Do you want to put the domain driver into /driver/soc/rockchip?
I guess the efuse driver ...is also do that.

Perhaps, it's a good select in the future.


>> (4) As Tomasz remarked previously the dts should represent the hardware and
>> the power-domains are part of the pmu. There is a recent addition from Linus
>> Walleij, called simple-mfd [a] that is supposed to get added real early for
>> kernel 4.2. So I'd think the power-domains should use that and the patchset
>> modified to include the changes shown below [b]?
>>
>> (5) Keven Hilman and Tomasz had reservations about all the device clocks
>> being listed in the power-domains itself in the previous versions. I don't see
>> a comment from them yet changing that view.
> Correct.

How about this patch?

https://patchwork.kernel.org/patch/5145241/

I will do that.

Maybe, do you have more suggestions?


>> Their wish was to get the clocks by reading the clocks from the device nodes,
>> though I see a problem on how to handle devices that do not have any bindings
>> at all yet.
>>
>> Kevin, Tomasz any new thoughts?
> I don't see any issues with devices that don't have bindings, as all
> that would be needed would be to simple device nodes with a clock
> property.  I wouldn't even matter if those devices had device drivers.
>
> Kevin
>
>
>



From heiko at sntech.de  Fri Jun 12 00:27:07 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 12 Jun 2015 09:27:07 +0200
Subject: [PATCH v3 1/2] drm/bridge: dw-hdmi: support optional supply
 regulators
In-Reply-To: <20150609233618.GK7557@n2100.arm.linux.org.uk>
References: <4184159.j0iXe39dFB@phil> <3551826.dyCjorKhLA@diego>
 <20150609233618.GK7557@n2100.arm.linux.org.uk>
Message-ID: <4099644.agHN3RgGum@diego>

Am Mittwoch, 10. Juni 2015, 00:36:18 schrieb Russell King - ARM Linux:
> On Wed, Jun 10, 2015 at 01:29:43AM +0200, Heiko St?bner wrote:
> > Allthough from the discussion and explanations I've now also got the
> > "don't
> > make it worse" feeling, so am somehow reluctant to add supplies that also
> > might describe this inadequately.
> > 
> > The Rockchip-specific documentation only lists the two supplies as
> > AVDD_1V0, AVDD_1V8 with a description of "DC supply voltage for Analog
> > part of HDMI". The supplies aren't mentioned otherwise at all, so I guess
> > I'll ponder this a bit more at first.
> 
> Are they controllable from software at all?  If they aren't, then
> I'd suggest leaving them out until we have a distinction between
> the Tx and Phy - much as we do for iMX6.

they are supplied by the pmic the system uses (named vdd10_lcd and vdd18_lcd 
in the soc manuals/schematics)  and supply the individual output encoder 
analog parts (hdmi, edp, lvds, etc).  So if there is no output at all, they 
should be able to be turned off.


From heiko at sntech.de  Fri Jun 12 11:59:53 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 12 Jun 2015 20:59:53 +0200
Subject: [PATCH RESEND] PM / AVS: rockchip-io: depend on CONFIG_POWER_AVS
Message-ID: <2264276.IR62hmqflk@diego>

The rockchip io-domain driver currently only depends on ARCH_ROCKCHIP
itself. This makes it possible to select the power-domain driver, but
not the POWER_AVS class and results in the iodomain-driver not getting
build in this case.

So add the additional dependency, which also results in the driver
config option now being placed nicely into the AVS submenu.

Fixes: 662a958638bd ("PM / AVS: rockchip-io: add driver handling Rockchip io domains")
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Acked-by: Kevin Hilman <khilman at linaro.org>
---
Kevin wrote when he Acked the patch: "Rafael, feel free to queue this
up as a fix.  I don't have any other drivers/power/avs stuff queued up."

 drivers/power/avs/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
index 7f3d389..a67eeac 100644
--- a/drivers/power/avs/Kconfig
+++ b/drivers/power/avs/Kconfig
@@ -13,7 +13,7 @@ menuconfig POWER_AVS
 
 config ROCKCHIP_IODOMAIN
         tristate "Rockchip IO domain support"
-        depends on ARCH_ROCKCHIP && OF
+        depends on POWER_AVS && ARCH_ROCKCHIP && OF
         help
           Say y here to enable support io domains on Rockchip SoCs. It is
           necessary for the io domain setting of the SoC to match the
-- 
2.1.4



From heiko at sntech.de  Fri Jun 12 14:50:11 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 12 Jun 2015 23:50:11 +0200
Subject: [PATCH 1/2] pinctrl: rockchip: generalize perpin driver-strength
 setting
Message-ID: <2322857.kblfsanYOB@diego>

The upcoming support for the RK3368 ARM64 SoC also supports perpin
drive strength settings (at different register positions), so generalize
the register and offset calculation to easily support this one too.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/pinctrl/pinctrl-rockchip.c | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index dee7d5f..70423ae 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -163,6 +163,9 @@ struct rockchip_pin_ctrl {
 	void	(*pull_calc_reg)(struct rockchip_pin_bank *bank,
 				    int pin_num, struct regmap **regmap,
 				    int *reg, u8 *bit);
+	void	(*drv_calc_reg)(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit);
 };
 
 struct rockchip_pin_config {
@@ -581,7 +584,6 @@ static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
 #define RK3288_DRV_BITS_PER_PIN		2
 #define RK3288_DRV_PINS_PER_REG		8
 #define RK3288_DRV_BANK_STRIDE		16
-static int rk3288_drv_list[] = { 2, 4, 8, 12 };
 
 static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 				    int pin_num, struct regmap **regmap,
@@ -611,14 +613,19 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 	}
 }
 
-static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
+static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 };
+
+static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
+				     int pin_num)
 {
+	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
 	int reg, ret;
 	u32 data;
 	u8 bit;
 
-	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
 	ret = regmap_read(regmap, reg, &data);
 	if (ret)
@@ -627,24 +634,25 @@ static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num)
 	data >>= bit;
 	data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1;
 
-	return rk3288_drv_list[data];
+	return rockchip_perpin_drv_list[data];
 }
 
-static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
-			    int strength)
+static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
+				     int pin_num, int strength)
 {
 	struct rockchip_pinctrl *info = bank->drvdata;
+	struct rockchip_pin_ctrl *ctrl = info->ctrl;
 	struct regmap *regmap;
 	unsigned long flags;
 	int reg, ret, i;
 	u32 data, rmask;
 	u8 bit;
 
-	rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
+	ctrl->drv_calc_reg(bank, pin_num, &regmap, &reg, &bit);
 
 	ret = -EINVAL;
-	for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) {
-		if (rk3288_drv_list[i] == strength) {
+	for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list); i++) {
+		if (rockchip_perpin_drv_list[i] == strength) {
 			ret = i;
 			break;
 		}
@@ -983,10 +991,11 @@ static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
 			break;
 		case PIN_CONFIG_DRIVE_STRENGTH:
 			/* rk3288 is the first with per-pin drive-strength */
-			if (info->ctrl->type != RK3288)
+			if (!info->ctrl->drv_calc_reg)
 				return -ENOTSUPP;
 
-			rc = rk3288_set_drive(bank, pin - bank->pin_base, arg);
+			rc = rockchip_set_drive_perpin(bank,
+						pin - bank->pin_base, arg);
 			if (rc < 0)
 				return rc;
 			break;
@@ -1041,10 +1050,10 @@ static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH:
 		/* rk3288 is the first with per-pin drive-strength */
-		if (info->ctrl->type != RK3288)
+		if (!info->ctrl->drv_calc_reg)
 			return -ENOTSUPP;
 
-		rc = rk3288_get_drive(bank, pin - bank->pin_base);
+		rc = rockchip_get_drive_perpin(bank, pin - bank->pin_base);
 		if (rc < 0)
 			return rc;
 
@@ -2056,6 +2065,7 @@ static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
 		.grf_mux_offset		= 0x0,
 		.pmu_mux_offset		= 0x84,
 		.pull_calc_reg		= rk3288_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3288_calc_drv_reg_and_bit,
 };
 
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
-- 
2.1.4




From heiko at sntech.de  Fri Jun 12 14:51:01 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 12 Jun 2015 23:51:01 +0200
Subject: [PATCH 2/2] pinctrl: rockchip: add support for the rk3368
In-Reply-To: <2322857.kblfsanYOB@diego>
References: <2322857.kblfsanYOB@diego>
Message-ID: <6672678.KPGUcFJOAs@diego>

The rk3368 is the first ARM64 soc from Rockchip, but seems to share most
peripherals with the ARM32 soc, including the pinctrl functionality.
The only notable difference is - as with every Rockchip soc - that the
offsets in the General Register Files moved around and a split of the pmu
section of the rk3288 into pmu and pmugrf (pmu general register files)
sections. The pinctrl driver of course only needs the pmugrf registers
for controlling the pin settings.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 .../bindings/pinctrl/rockchip,pinctrl.txt          |  5 +-
 drivers/pinctrl/pinctrl-rockchip.c                 | 91 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
index 388b213..391ef4b 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
@@ -21,14 +21,15 @@ defined as gpio sub-nodes of the pinmux controller.
 Required properties for iomux controller:
   - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
 		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
-		       "rockchip,rk3288-pinctrl"
+		       "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
 	 "general register files"
 
 Optional properties for iomux controller:
   - rockchip,pmu: phandle referencing a syscon providing the pmu registers
 	 as some SoCs carry parts of the iomux controller registers there.
-	 Required for at least rk3188 and rk3288.
+	 Required for at least rk3188 and rk3288. On the rk3368 this should
+	 point to the PMUGRF syscon.
 
 Deprecated properties for iomux controller:
   - reg: first element is the general register space of the iomux controller
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 70423ae..7234125 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -63,6 +63,7 @@ enum rockchip_pinctrl_type {
 	RK3066B,
 	RK3188,
 	RK3288,
+	RK3368,
 };
 
 /**
@@ -613,6 +614,68 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 	}
 }
 
+#define RK3368_PULL_GRF_OFFSET		0x100
+#define RK3368_PULL_PMU_OFFSET		0x10
+
+static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3368_PULL_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3188_PULL_PINS_PER_REG;
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3368_PULL_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+		*reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+		*bit *= RK3188_PULL_BITS_PER_PIN;
+	}
+}
+
+#define RK3368_DRV_PMU_OFFSET		0x20
+#define RK3368_DRV_GRF_OFFSET		0x200
+
+static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+				    int pin_num, struct regmap **regmap,
+				    int *reg, u8 *bit)
+{
+	struct rockchip_pinctrl *info = bank->drvdata;
+
+	/* The first 32 pins of the first bank are located in PMU */
+	if (bank->bank_num == 0) {
+		*regmap = info->regmap_pmu;
+		*reg = RK3368_DRV_PMU_OFFSET;
+
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+		*bit = pin_num % RK3288_DRV_PINS_PER_REG;
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	} else {
+		*regmap = info->regmap_base;
+		*reg = RK3368_DRV_GRF_OFFSET;
+
+		/* correct the offset, as we're starting with the 2nd bank */
+		*reg -= 0x10;
+		*reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+		*reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+		*bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+		*bit *= RK3288_DRV_BITS_PER_PIN;
+	}
+}
+
 static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 };
 
 static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank,
@@ -703,6 +766,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
 				: PIN_CONFIG_BIAS_DISABLE;
 	case RK3188:
 	case RK3288:
+	case RK3368:
 		data >>= bit;
 		data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1;
 
@@ -758,6 +822,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 		break;
 	case RK3188:
 	case RK3288:
+	case RK3368:
 		spin_lock_irqsave(&bank->slock, flags);
 
 		/* enable the write to the equivalent lower bits */
@@ -935,6 +1000,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
 		return pull ? false : true;
 	case RK3188:
 	case RK3288:
+	case RK3368:
 		return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT);
 	}
 
@@ -2068,6 +2134,29 @@ static struct rockchip_pin_ctrl rk3288_pin_ctrl = {
 		.drv_calc_reg		= rk3288_calc_drv_reg_and_bit,
 };
 
+static struct rockchip_pin_bank rk3368_pin_banks[] = {
+	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU,
+					     IOMUX_SOURCE_PMU
+			    ),
+	PIN_BANK(1, 32, "gpio1"),
+	PIN_BANK(2, 32, "gpio2"),
+	PIN_BANK(3, 32, "gpio3"),
+};
+
+static struct rockchip_pin_ctrl rk3368_pin_ctrl = {
+		.pin_banks		= rk3368_pin_banks,
+		.nr_banks		= ARRAY_SIZE(rk3368_pin_banks),
+		.label			= "RK3368-GPIO",
+		.type			= RK3368,
+		.grf_mux_offset		= 0x0,
+		.pmu_mux_offset		= 0x0,
+		.pull_calc_reg		= rk3368_calc_pull_reg_and_bit,
+		.drv_calc_reg		= rk3368_calc_drv_reg_and_bit,
+};
+
+
 static const struct of_device_id rockchip_pinctrl_dt_match[] = {
 	{ .compatible = "rockchip,rk2928-pinctrl",
 		.data = (void *)&rk2928_pin_ctrl },
@@ -2079,6 +2168,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
 		.data = (void *)&rk3188_pin_ctrl },
 	{ .compatible = "rockchip,rk3288-pinctrl",
 		.data = (void *)&rk3288_pin_ctrl },
+	{ .compatible = "rockchip,rk3368-pinctrl",
+		.data = (void *)&rk3368_pin_ctrl },
 	{},
 };
 MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match);
-- 
2.1.4




From heiko at sntech.de  Sat Jun 13 03:13:04 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Sat, 13 Jun 2015 12:13:04 +0200
Subject: [PATCH] iio: adc: rockchip_saradc: add missing MODULE_* data
In-Reply-To: <4303804.647s4ZjWfi@phil>
References: <4303804.647s4ZjWfi@phil>
Message-ID: <1551389.A2qkCOk6hp@diego>

Am Montag, 25. Mai 2015, 22:36:58 schrieb Heiko Stuebner:
> The module-data is currently missing. This includes the license-information
> which makes the driver taint the kernel and miss symbols when compiled as
> module.
> 
> Fixes: 44d6f2ef94f9 ("iio: adc: add driver for Rockchip saradc")
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---

ping on this patch?


Heiko


From heiko at sntech.de  Sat Jun 13 09:22:14 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:14 +0200
Subject: [PATCH 0/8] clk: rockchip: add support for the clock-tree of the
 rk3368
Message-ID: <1434212542-17145-1-git-send-email-heiko@sntech.de>

This series adds support for the clock controller of rk3368
ARM64 socs.

The first 2 patches are fixes for small issues I found while
building the clocktree. Both do not harm the functionality
of the older socs, as there is no camera interface driver in
them anyway and the issue with the defines only surfaced on
the rk3368.

Patch 3 then adds a new definition for a branch-type.

Some clocks (mainly the hsadc and camera interfaces) have a phase
inverter connected to the clock that makes it possible to adjust
the clock phase by 180 degrees. Patches 4 and 5 finally add
support for these inverters and add the currently missing
definitions to the already present clock drivers.

Patches 6, 7 and 8 finally add the shared dt-binding header and
the rk3368 clock tree itself. The cpu-clocks in there where
tested sucessfully with the big_little_cpufreq driver.


Heiko Stuebner (8):
  clk: rockchip: protect register macros against multipart values
  clk: rockchip: fix faulty vip parent name on rk3288
  clk: rockchip: add COMPOSITE_NOGATE_DIVTBL variant
  clk: rockchip: add support for phase inverters
  clk: rockchip: define the inverters of rk3066/rk3188 and rk3288
  dt-bindings: add documentation of rk3668 clock controller
  clk: rockchip: add dt-binding header for rk3368
  clk: rockchip: add rk3368 clock controller

 .../bindings/clock/rockchip,rk3368-cru.txt         |  61 ++
 drivers/clk/rockchip/Makefile                      |   2 +
 drivers/clk/rockchip/clk-inverter.c                | 126 +++
 drivers/clk/rockchip/clk-rk3188.c                  |   9 +-
 drivers/clk/rockchip/clk-rk3288.c                  |  11 +-
 drivers/clk/rockchip/clk-rk3368.c                  | 881 +++++++++++++++++++++
 drivers/clk/rockchip/clk.c                         |   7 +
 drivers/clk/rockchip/clk.h                         |  72 +-
 include/dt-bindings/clock/rk3368-cru.h             | 379 +++++++++
 9 files changed, 1536 insertions(+), 12 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
 create mode 100644 drivers/clk/rockchip/clk-inverter.c
 create mode 100644 drivers/clk/rockchip/clk-rk3368.c
 create mode 100644 include/dt-bindings/clock/rk3368-cru.h

-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:16 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:16 +0200
Subject: [PATCH 2/8] clk: rockchip: fix faulty vip parent name on rk3288
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-3-git-send-email-heiko@sntech.de>

The video input processor (vip) was called camera interface (cif) on
older socs which seems to have resulted in a copy'n'paste error when
creating the rk3288 camera clocks.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk-rk3288.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 4f817ed..6f0259f 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -189,7 +189,7 @@ PNAME(mux_uart1_p)	= { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)	= { "uart2_src", "uart2_frac", "xin24m" };
 PNAME(mux_uart3_p)	= { "uart3_src", "uart3_frac", "xin24m" };
 PNAME(mux_uart4_p)	= { "uart4_src", "uart4_frac", "xin24m" };
-PNAME(mux_cif_out_p)	= { "cif_src", "xin24m" };
+PNAME(mux_vip_out_p)	= { "vip_src", "xin24m" };
 PNAME(mux_mac_p)	= { "mac_pll_src", "ext_gmac" };
 PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
@@ -434,7 +434,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
 			RK3288_CLKGATE_CON(3), 7, GFLAGS),
-	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
 			RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
 
 	DIV(0, "pclk_pd_alive", "gpll", 0,
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:17 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:17 +0200
Subject: [PATCH 3/8] clk: rockchip: add COMPOSITE_NOGATE_DIVTBL variant
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-4-git-send-email-heiko@sntech.de>

A clock branch consisting of a mux and divider with non-standard
divider values.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 92edb5f..501f02e 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -308,6 +308,26 @@ struct rockchip_clk_branch {
 		.gate_offset	= -1,				\
 	}
 
+#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms,	\
+				mw, mf, ds, dw, df, dt)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.div_table	= dt,				\
+		.gate_offset	= -1,				\
+	}
+
 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
 	{							\
 		.id		= _id,				\
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:15 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:15 +0200
Subject: [PATCH 1/8] clk: rockchip: protect register macros against multipart
 values
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-2-git-send-email-heiko@sntech.de>

The macros calculate the correct offset from the id in the parameter.
If this parameter does not consist of a single number, the calculation
will return wrong registers in the best case or create unaligned accesses
in the worst case. So protect the calculations against such values.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 6b09267..92edb5f 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -31,22 +31,22 @@
 		((val) << (shift) | (mask) << ((shift) + 16))
 
 /* register positions shared by RK2928, RK3066 and RK3188 */
-#define RK2928_PLL_CON(x)		(x * 0x4)
+#define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
-#define RK2928_CLKSEL_CON(x)	(x * 0x4 + 0x44)
-#define RK2928_CLKGATE_CON(x)	(x * 0x4 + 0xd0)
+#define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x)	((x) * 0x4 + 0xd0)
 #define RK2928_GLB_SRST_FST		0x100
 #define RK2928_GLB_SRST_SND		0x104
-#define RK2928_SOFTRST_CON(x)	(x * 0x4 + 0x110)
+#define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON		0x134
 
 #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
 #define RK3288_MODE_CON			0x50
-#define RK3288_CLKSEL_CON(x)		(x * 0x4 + 0x60)
-#define RK3288_CLKGATE_CON(x)		(x * 0x4 + 0x160)
+#define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x)		((x) * 0x4 + 0x160)
 #define RK3288_GLB_SRST_FST		0x1b0
 #define RK3288_GLB_SRST_SND		0x1b4
-#define RK3288_SOFTRST_CON(x)		(x * 0x4 + 0x1b8)
+#define RK3288_SOFTRST_CON(x)		((x) * 0x4 + 0x1b8)
 #define RK3288_MISC_CON			0x1e8
 #define RK3288_SDMMC_CON0		0x200
 #define RK3288_SDMMC_CON1		0x204
@@ -67,7 +67,7 @@ enum rockchip_pll_type {
 	.nr = _nr,				\
 	.nf = _nf,				\
 	.no = _no,				\
-	.bwadj = (_nf >> 1),			\
+	.bwadj = ((_nf) >> 1),			\
 }
 
 #define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw)	\
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:19 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:19 +0200
Subject: [PATCH 5/8] clk: rockchip: define the inverters of rk3066/rk3188 and
 rk3288
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-6-git-send-email-heiko@sntech.de>

Both soc series' have inverters on the hsadc and camera interface clock
paths. So define them using the newly added inverter type.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk-rk3188.c | 9 ++++++++-
 drivers/clk/rockchip/clk-rk3288.c | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index e4f9d47..a9ab4f9 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -235,6 +235,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 /* 2 ^ (val + 1) */
 static struct clk_div_table div_core_peri_t[] = {
@@ -310,6 +311,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 
 	GATE(0, "pclkin_cif0", "ext_cif0", 0,
 			RK2928_CLKGATE_CON(3), 3, GFLAGS),
+	INVERTER(0, "pclk_cif0", "pclkin_cif0",
+			RK2928_CLKSEL_CON(30), 8, IFLAGS),
 
 	/*
 	 * the 480m are generated inside the usb block from these clocks,
@@ -334,8 +337,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
 			RK2928_CLKGATE_CON(2), 7, GFLAGS),
-	MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
 			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
 	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
 			RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
@@ -557,6 +562,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 
 	GATE(0, "pclkin_cif1", "ext_cif1", 0,
 			RK2928_CLKGATE_CON(3), 4, GFLAGS),
+	INVERTER(0, "pclk_cif1", "pclkin_cif1",
+			RK2928_CLKSEL_CON(30), 12, IFLAGS),
 
 	COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
 			RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 6f0259f..a0c639f 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -223,6 +223,7 @@ static struct clk_div_table div_hclk_cpu_t[] = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	/*
@@ -592,8 +593,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
 			RK3288_CLKGATE_CON(2), 6, GFLAGS),
-	MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+	MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0,
 			RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+			RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
 	GATE(0, "jtag", "ext_jtag", 0,
 			RK3288_CLKGATE_CON(4), 14, GFLAGS),
@@ -768,7 +771,9 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	 */
 
 	GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+	INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
 	GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+	INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
 };
 
 static const char *const rk3288_critical_clocks[] __initconst = {
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:20 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:20 +0200
Subject: [PATCH 6/8] dt-bindings: add documentation of rk3668 clock controller
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-7-git-send-email-heiko@sntech.de>

Add the devicetree binding for the cru on the rk3368 which quite similar
structured as previous clock controllers.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: devicetree at vger.kernel.org
---
 .../bindings/clock/rockchip,rk3368-cru.txt         | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt

diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
new file mode 100644
index 0000000..0815df5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
@@ -0,0 +1,61 @@
+* Rockchip RK3368 Clock and Reset Unit
+
+The RK3368 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3368-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing, pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3368-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+ - "ext_vip" - external VIP clock - optional,
+ - "usbotg_out" - output clock of the pll in the otg phy
+
+Example: Clock controller node:
+
+	cru: clock-controller at ff760000 {
+		compatible = "rockchip,rk3368-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial at 10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clocks = <&cru SCLK_UART0>;
+	};
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:18 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:18 +0200
Subject: [PATCH 4/8] clk: rockchip: add support for phase inverters
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-5-git-send-email-heiko@sntech.de>

Most Rockchip socs have optional phase inverters connected to some
clocks that move the clock-phase by 180 degrees.
While not having any actual influence on the rate, the inverter
provides its own simple recalc_rate callback as relying on the
fallback in the framework is for "lazy developers" according
to the documentation in the code.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/Makefile       |   1 +
 drivers/clk/rockchip/clk-inverter.c | 126 ++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.c          |   7 ++
 drivers/clk/rockchip/clk.h          |  20 ++++++
 4 files changed, 154 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-inverter.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 2714097..fd71c7d 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -6,6 +6,7 @@ obj-y	+= clk-rockchip.o
 obj-y	+= clk.o
 obj-y	+= clk-pll.o
 obj-y	+= clk-cpu.o
+obj-y	+= clk-inverter.o
 obj-y	+= clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c
new file mode 100644
index 0000000..db852cd
--- /dev/null
+++ b/drivers/clk/rockchip/clk-inverter.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include "clk.h"
+
+struct rockchip_inv_clock {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	int		shift;
+	int		flags;
+	spinlock_t	*lock;
+};
+
+#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
+
+#define INVERTER_MASK 0x1
+
+static unsigned long rockchip_inv_recalc(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	return parent_rate;
+}
+
+static int rockchip_inv_get_phase(struct clk_hw *hw)
+{
+	struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+	u32 val;
+
+	val = readl(inv_clock->reg) >> (inv_clock->shift) & INVERTER_MASK;
+	return val ? 180 : 0;
+}
+
+static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+	u32 val;
+
+	switch (degrees) {
+	case 0:
+		val = 0;
+		break;
+	case 180:
+		val = 1;
+		break;
+	default:
+		pr_err("%s: unsupported phase %d for %s\n",
+		       __func__, degrees, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
+		writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
+		       inv_clock->reg);
+	} else {
+		unsigned long flags;
+		u32 reg;
+
+		spin_lock_irqsave(inv_clock->lock, flags);
+
+		reg = readl(inv_clock->reg);
+		reg &= ~BIT(inv_clock->shift);
+		reg |= val;
+		writel(reg, inv_clock->reg);
+
+		spin_unlock_irqrestore(inv_clock->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops rockchip_inv_clk_ops = {
+	.recalc_rate	= rockchip_inv_recalc,
+	.get_phase	= rockchip_inv_get_phase,
+	.set_phase	= rockchip_inv_set_phase,
+};
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+				const char *const *parent_names, u8 num_parents,
+				void __iomem *reg, int shift, int flags,
+				spinlock_t *lock)
+{
+	struct clk_init_data init;
+	struct rockchip_inv_clock *inv_clock;
+	struct clk *clk;
+
+	inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
+	if (!inv_clock)
+		return NULL;
+
+	init.num_parents = num_parents;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_names;
+	init.ops = &rockchip_inv_clk_ops;
+
+	inv_clock->hw.init = &init;
+	inv_clock->reg = reg;
+	inv_clock->shift = shift;
+	inv_clock->flags = flags;
+	inv_clock->lock = lock;
+
+	if (name)
+		init.name = name;
+
+	clk = clk_register(NULL, &inv_clock->hw);
+	if (IS_ERR(clk))
+		goto err_free;
+
+	return clk;
+
+err_free:
+	kfree(inv_clock);
+	return NULL;
+}
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 052b94d..2493881 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -277,6 +277,13 @@ void __init rockchip_clk_register_branches(
 				list->div_shift
 			);
 			break;
+		case branch_inverter:
+			clk = rockchip_clk_register_inverter(
+				list->name, list->parent_names,
+				list->num_parents,
+				reg_base + list->muxdiv_offset,
+				list->div_shift, list->div_flags, &clk_lock);
+			break;
 		}
 
 		/* none of the cases above matched */
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 501f02e..b72dad0 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -182,6 +182,13 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift);
 
+#define ROCKCHIP_INVERTER_HIWORD_MASK	BIT(0)
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+				const char *const *parent_names, u8 num_parents,
+				void __iomem *reg, int shift, int flags,
+				spinlock_t *lock);
+
 #define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
@@ -191,6 +198,7 @@ enum rockchip_clk_branch_type {
 	branch_fraction_divider,
 	branch_gate,
 	branch_mmc,
+	branch_inverter,
 };
 
 struct rockchip_clk_branch {
@@ -414,6 +422,18 @@ struct rockchip_clk_branch {
 		.div_shift	= shift,			\
 	}
 
+#define INVERTER(_id, cname, pname, io, is, if)			\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_inverter,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.muxdiv_offset	= io,				\
+		.div_shift	= is,				\
+		.div_flags	= if,				\
+	}
+
 void rockchip_clk_init(struct device_node *np, void __iomem *base,
 		       unsigned long nr_clks);
 struct regmap *rockchip_clk_get_grf(void);
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:21 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:21 +0200
Subject: [PATCH 7/8] clk: rockchip: add dt-binding header for rk3368
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-8-git-send-email-heiko@sntech.de>

Add the dt-bindings header for the rk3368, that gets shared between
the clock controller and the clock references in the dts.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 include/dt-bindings/clock/rk3368-cru.h | 379 +++++++++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk3368-cru.h

diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h
new file mode 100644
index 0000000..6280753
--- /dev/null
+++ b/include/dt-bindings/clock/rk3368-cru.h
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+/* core clocks */
+#define PLL_APLLB		1
+#define PLL_APLLL		2
+#define PLL_DPLL		3
+#define PLL_CPLL		4
+#define PLL_GPLL		5
+#define PLL_NPLL		6
+#define ARMCLKB			7
+#define ARMCLKL			8
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU_CORE		64
+#define SCLK_SPI0		65
+#define SCLK_SPI1		66
+#define SCLK_SPI2		67
+#define SCLK_SDMMC		68
+#define SCLK_SDIO0		69
+#define SCLK_EMMC		71
+#define SCLK_TSADC		72
+#define SCLK_SARADC		73
+#define SCLK_NANDC0		75
+#define SCLK_UART0		77
+#define SCLK_UART1		78
+#define SCLK_UART2		79
+#define SCLK_UART3		80
+#define SCLK_UART4		81
+#define SCLK_I2S_8CH		82
+#define SCLK_SPDIF_8CH		83
+#define SCLK_I2S_2CH		84
+#define SCLK_TIMER0		85
+#define SCLK_TIMER1		86
+#define SCLK_TIMER2		87
+#define SCLK_TIMER3		88
+#define SCLK_TIMER4		89
+#define SCLK_TIMER5		90
+#define SCLK_TIMER6		91
+#define SCLK_OTGPHY0		93
+#define SCLK_OTG_ADP		96
+#define SCLK_HSICPHY480M	97
+#define SCLK_HSICPHY12M		98
+#define SCLK_MACREF		99
+#define SCLK_VOP0_PWM		100
+#define SCLK_MAC_RX		102
+#define SCLK_MAC_TX		103
+#define SCLK_EDP_24M		104
+#define SCLK_EDP		105
+#define SCLK_RGA		106
+#define SCLK_ISP		107
+#define SCLK_HDCP		108
+#define SCLK_HDMI_HDCP		109
+#define SCLK_HDMI_CEC		110
+#define SCLK_HEVC_CABAC		111
+#define SCLK_HEVC_CORE		112
+#define SCLK_I2S_8CH_OUT	113
+#define SCLK_SDMMC_DRV		114
+#define SCLK_SDIO0_DRV		115
+#define SCLK_EMMC_DRV		117
+#define SCLK_SDMMC_SAMPLE	118
+#define SCLK_SDIO0_SAMPLE	119
+#define SCLK_EMMC_SAMPLE	121
+#define SCLK_USBPHY480M		122
+#define SCLK_PVTM_CORE		123
+#define SCLK_PVTM_GPU		124
+#define SCLK_PVTM_PMU		125
+#define SCLK_SFC		126
+#define SCLK_MAC		127
+#define SCLK_MACREF_OUT		128
+
+#define DCLK_VOP		190
+#define MCLK_CRYPTO		191
+
+/* aclk gates */
+#define ACLK_GPU_MEM		192
+#define ACLK_GPU_CFG		193
+#define ACLK_DMAC_BUS		194
+#define ACLK_DMAC_PERI		195
+#define ACLK_PERI_MMU		196
+#define ACLK_GMAC		197
+#define ACLK_VOP		198
+#define ACLK_VOP_IEP		199
+#define ACLK_RGA		200
+#define ACLK_HDCP		201
+#define ACLK_IEP		202
+#define ACLK_VIO0_NOC		203
+#define ACLK_VIP		204
+#define ACLK_ISP		205
+#define ACLK_VIO1_NOC		206
+#define ACLK_VIDEO		208
+#define ACLK_BUS		209
+#define ACLK_PERI		210
+
+/* pclk gates */
+#define PCLK_GPIO0		320
+#define PCLK_GPIO1		321
+#define PCLK_GPIO2		322
+#define PCLK_GPIO3		323
+#define PCLK_PMUGRF		324
+#define PCLK_MAILBOX		325
+#define PCLK_GRF		329
+#define PCLK_SGRF		330
+#define PCLK_PMU		331
+#define PCLK_I2C0		332
+#define PCLK_I2C1		333
+#define PCLK_I2C2		334
+#define PCLK_I2C3		335
+#define PCLK_I2C4		336
+#define PCLK_I2C5		337
+#define PCLK_SPI0		338
+#define PCLK_SPI1		339
+#define PCLK_SPI2		340
+#define PCLK_UART0		341
+#define PCLK_UART1		342
+#define PCLK_UART2		343
+#define PCLK_UART3		344
+#define PCLK_UART4		345
+#define PCLK_TSADC		346
+#define PCLK_SARADC		347
+#define PCLK_SIM		348
+#define PCLK_GMAC		349
+#define PCLK_PWM0		350
+#define PCLK_PWM1		351
+#define PCLK_TIMER0		353
+#define PCLK_TIMER1		354
+#define PCLK_EDP_CTRL		355
+#define PCLK_MIPI_DSI0		356
+#define PCLK_MIPI_CSI		358
+#define PCLK_HDCP		359
+#define PCLK_HDMI_CTRL		360
+#define PCLK_VIO_H2P		361
+#define PCLK_BUS		362
+#define PCLK_PERI		363
+#define PCLK_DDRUPCTL		364
+#define PCLK_DDRPHY		365
+#define PCLK_ISP		366
+#define PCLK_VIP		367
+#define PCLK_WDT		368
+
+/* hclk gates */
+#define HCLK_SFC		448
+#define HCLK_OTG0		449
+#define HCLK_HOST0		450
+#define HCLK_HOST1		451
+#define HCLK_HSIC		452
+#define HCLK_NANDC0		453
+#define HCLK_TSP		455
+#define HCLK_SDMMC		456
+#define HCLK_SDIO0		457
+#define HCLK_EMMC		459
+#define HCLK_HSADC		460
+#define HCLK_CRYPTO		461
+#define HCLK_I2S_2CH		462
+#define HCLK_I2S_8CH		463
+#define HCLK_SPDIF		464
+#define HCLK_VOP		465
+#define HCLK_ROM		467
+#define HCLK_IEP		468
+#define HCLK_ISP		469
+#define HCLK_RGA		470
+#define HCLK_VIO_AHB_ARBI	471
+#define HCLK_VIO_NOC		472
+#define HCLK_VIP		473
+#define HCLK_VIO_H2P		474
+#define HCLK_VIO_HDCPMMU	475
+#define HCLK_VIDEO		476
+#define HCLK_BUS		477
+#define HCLK_PERI		478
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE_B0		0
+#define SRST_CORE_B1		1
+#define SRST_CORE_B2		2
+#define SRST_CORE_B3		3
+#define SRST_CORE_B0_PO		4
+#define SRST_CORE_B1_PO		5
+#define SRST_CORE_B2_PO		6
+#define SRST_CORE_B3_PO		7
+#define SRST_L2_B		8
+#define SRST_ADB_B		9
+#define SRST_PD_CORE_B_NIU	10
+#define SRST_PDBUS_STRSYS	11
+#define SRST_SOCDBG_B		14
+#define SRST_CORE_B_DBG		15
+
+#define SRST_DMAC1		18
+#define SRST_INTMEM		19
+#define SRST_ROM		20
+#define SRST_SPDIF8CH		21
+#define SRST_I2S8CH		23
+#define SRST_MAILBOX		24
+#define SRST_I2S2CH		25
+#define SRST_EFUSE_256		26
+#define SRST_MCU_SYS		28
+#define SRST_MCU_PO		29
+#define SRST_MCU_NOC		30
+#define SRST_EFUSE		31
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_GPIO3		35
+#define SRST_GPIO4		36
+#define SRST_PMUGRF		41
+#define SRST_I2C0		42
+#define SRST_I2C1		43
+#define SRST_I2C2		44
+#define SRST_I2C3		45
+#define SRST_I2C4		46
+#define SRST_I2C5		47
+
+#define SRST_DWPWM		48
+#define SRST_MMC_PERI		49
+#define SRST_PERIPH_MMU		50
+#define SRST_GRF		55
+#define SRST_PMU		56
+#define SRST_PERIPH_AXI		57
+#define SRST_PERIPH_AHB		58
+#define SRST_PERIPH_APB		59
+#define SRST_PERIPH_NIU		60
+#define SRST_PDPERI_AHB_ARBI	61
+#define SRST_EMEM		62
+#define SRST_USB_PERI		63
+
+#define SRST_DMAC2		64
+#define SRST_MAC		66
+#define SRST_GPS		67
+#define SRST_RKPWM		69
+#define SRST_USBHOST0		72
+#define SRST_HSIC		73
+#define SRST_HSIC_AUX		74
+#define SRST_HSIC_PHY		75
+#define SRST_HSADC		76
+#define SRST_NANDC0		77
+#define SRST_SFC		79
+
+#define SRST_SPI0		83
+#define SRST_SPI1		84
+#define SRST_SPI2		85
+#define SRST_SARADC		87
+#define SRST_PDALIVE_NIU	88
+#define SRST_PDPMU_INTMEM	89
+#define SRST_PDPMU_NIU		90
+#define SRST_SGRF		91
+
+#define SRST_VIO_ARBI		96
+#define SRST_RGA_NIU		97
+#define SRST_VIO0_NIU_AXI	98
+#define SRST_VIO_NIU_AHB	99
+#define SRST_LCDC0_AXI		100
+#define SRST_LCDC0_AHB		101
+#define SRST_LCDC0_DCLK		102
+#define SRST_VIP		104
+#define SRST_RGA_CORE		105
+#define SRST_IEP_AXI		106
+#define SRST_IEP_AHB		107
+#define SRST_RGA_AXI		108
+#define SRST_RGA_AHB		109
+#define SRST_ISP		110
+#define SRST_EDP_24M		111
+
+#define SRST_VIDEO_AXI		112
+#define SRST_VIDEO_AHB		113
+#define SRST_MIPIDPHYTX		114
+#define SRST_MIPIDSI0		115
+#define SRST_MIPIDPHYRX		116
+#define SRST_MIPICSI		117
+#define SRST_GPU		120
+#define SRST_HDMI		121
+#define SRST_EDP		122
+#define SRST_PMU_PVTM		123
+#define SRST_CORE_PVTM		124
+#define SRST_GPU_PVTM		125
+#define SRST_GPU_SYS		126
+#define SRST_GPU_MEM_NIU	127
+
+#define SRST_MMC0		128
+#define SRST_SDIO0		129
+#define SRST_EMMC		131
+#define SRST_USBOTG_AHB		132
+#define SRST_USBOTG_PHY		133
+#define SRST_USBOTG_CON		134
+#define SRST_USBHOST0_AHB	135
+#define SRST_USBHOST0_PHY	136
+#define SRST_USBHOST0_CON	137
+#define SRST_USBOTG_UTMI	138
+#define SRST_USBHOST1_UTMI	139
+#define SRST_USB_ADP		141
+
+#define SRST_CORESIGHT		144
+#define SRST_PD_CORE_AHB_NOC	145
+#define SRST_PD_CORE_APB_NOC	146
+#define SRST_GIC		148
+#define SRST_LCDC_PWM0		149
+#define SRST_RGA_H2P_BRG	153
+#define SRST_VIDEO		154
+#define SRST_GPU_CFG_NIU	157
+#define SRST_TSADC		159
+
+#define SRST_DDRPHY0		160
+#define SRST_DDRPHY0_APB	161
+#define SRST_DDRCTRL0		162
+#define SRST_DDRCTRL0_APB	163
+#define SRST_VIDEO_NIU		165
+#define SRST_VIDEO_NIU_AHB	167
+#define SRST_DDRMSCH0		170
+#define SRST_PDBUS_AHB		173
+#define SRST_CRYPTO		174
+
+#define SRST_UART0		179
+#define SRST_UART1		180
+#define SRST_UART2		181
+#define SRST_UART3		182
+#define SRST_UART4		183
+#define SRST_SIMC		186
+#define SRST_TSP		188
+#define SRST_TSP_CLKIN0		189
+
+#define SRST_CORE_L0		192
+#define SRST_CORE_L1		193
+#define SRST_CORE_L2		194
+#define SRST_CORE_L3		195
+#define SRST_CORE_L0_PO		195
+#define SRST_CORE_L1_PO		197
+#define SRST_CORE_L2_PO		198
+#define SRST_CORE_L3_PO		199
+#define SRST_L2_L		200
+#define SRST_ADB_L		201
+#define SRST_PD_CORE_L_NIU	202
+#define SRST_CCI_SYS		203
+#define SRST_CCI_DDR		204
+#define SRST_CCI		205
+#define SRST_SOCDBG_L		206
+#define SRST_CORE_L_DBG		207
+
+#define SRST_CORE_B0_NC		208
+#define SRST_CORE_B0_PO_NC	209
+#define SRST_L2_B_NC		210
+#define SRST_ADB_B_NC		211
+#define SRST_PD_CORE_B_NIU_NC	212
+#define SRST_PDBUS_STRSYS_NC	213
+#define SRST_CORE_L0_NC		214
+#define SRST_CORE_L0_PO_NC	215
+#define SRST_L2_L_NC		216
+#define SRST_ADB_L_NC		217
+#define SRST_PD_CORE_L_NIU_NC	218
+#define SRST_CCI_SYS_NC		219
+#define SRST_CCI_DDR_NC		220
+#define SRST_CCI_NC		221
+#define SRST_TRACE_NC		222
+
+#define SRST_TIMER00		224
+#define SRST_TIMER01		225
+#define SRST_TIMER02		226
+#define SRST_TIMER03		227
+#define SRST_TIMER04		228
+#define SRST_TIMER05		229
+#define SRST_TIMER10		230
+#define SRST_TIMER11		231
+#define SRST_TIMER12		232
+#define SRST_TIMER13		233
+#define SRST_TIMER14		234
+#define SRST_TIMER15		235
+#define SRST_TIMER0_APB		236
+#define SRST_TIMER1_APB		237
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 09:22:22 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sat, 13 Jun 2015 18:22:22 +0200
Subject: [PATCH 8/8] clk: rockchip: add rk3368 clock controller
In-Reply-To: <1434212542-17145-1-git-send-email-heiko@sntech.de>
References: <1434212542-17145-1-git-send-email-heiko@sntech.de>
Message-ID: <1434212542-17145-9-git-send-email-heiko@sntech.de>

Describe the clock tree and software resets of the rk3368 ARM64 SoC

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/Makefile     |   1 +
 drivers/clk/rockchip/clk-rk3368.c | 881 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h        |  16 +
 3 files changed, 898 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-rk3368.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index fd71c7d..b27edd6 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3288.o
+obj-y	+= clk-rk3368.o
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
new file mode 100644
index 0000000..4cf5758
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3368.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/rk3368-cru.h>
+#include "clk.h"
+
+#define RK3368_GRF_SOC_STATUS0	0x480
+
+enum rk3368_plls {
+	apllb, aplll, dpll, cpll, gpll, npll,
+};
+
+static struct rockchip_pll_rate_table rk3368_pll_rates[] = {
+	RK3066_PLL_RATE(2208000000, 1, 92, 1),
+	RK3066_PLL_RATE(2184000000, 1, 91, 1),
+	RK3066_PLL_RATE(2160000000, 1, 90, 1),
+	RK3066_PLL_RATE(2136000000, 1, 89, 1),
+	RK3066_PLL_RATE(2112000000, 1, 88, 1),
+	RK3066_PLL_RATE(2088000000, 1, 87, 1),
+	RK3066_PLL_RATE(2064000000, 1, 86, 1),
+	RK3066_PLL_RATE(2040000000, 1, 85, 1),
+	RK3066_PLL_RATE(2016000000, 1, 84, 1),
+	RK3066_PLL_RATE(1992000000, 1, 83, 1),
+	RK3066_PLL_RATE(1968000000, 1, 82, 1),
+	RK3066_PLL_RATE(1944000000, 1, 81, 1),
+	RK3066_PLL_RATE(1920000000, 1, 80, 1),
+	RK3066_PLL_RATE(1896000000, 1, 79, 1),
+	RK3066_PLL_RATE(1872000000, 1, 78, 1),
+	RK3066_PLL_RATE(1848000000, 1, 77, 1),
+	RK3066_PLL_RATE(1824000000, 1, 76, 1),
+	RK3066_PLL_RATE(1800000000, 1, 75, 1),
+	RK3066_PLL_RATE(1776000000, 1, 74, 1),
+	RK3066_PLL_RATE(1752000000, 1, 73, 1),
+	RK3066_PLL_RATE(1728000000, 1, 72, 1),
+	RK3066_PLL_RATE(1704000000, 1, 71, 1),
+	RK3066_PLL_RATE(1680000000, 1, 70, 1),
+	RK3066_PLL_RATE(1656000000, 1, 69, 1),
+	RK3066_PLL_RATE(1632000000, 1, 68, 1),
+	RK3066_PLL_RATE(1608000000, 1, 67, 1),
+	RK3066_PLL_RATE(1560000000, 1, 65, 1),
+	RK3066_PLL_RATE(1512000000, 1, 63, 1),
+	RK3066_PLL_RATE(1488000000, 1, 62, 1),
+	RK3066_PLL_RATE(1464000000, 1, 61, 1),
+	RK3066_PLL_RATE(1440000000, 1, 60, 1),
+	RK3066_PLL_RATE(1416000000, 1, 59, 1),
+	RK3066_PLL_RATE(1392000000, 1, 58, 1),
+	RK3066_PLL_RATE(1368000000, 1, 57, 1),
+	RK3066_PLL_RATE(1344000000, 1, 56, 1),
+	RK3066_PLL_RATE(1320000000, 1, 55, 1),
+	RK3066_PLL_RATE(1296000000, 1, 54, 1),
+	RK3066_PLL_RATE(1272000000, 1, 53, 1),
+	RK3066_PLL_RATE(1248000000, 1, 52, 1),
+	RK3066_PLL_RATE(1224000000, 1, 51, 1),
+	RK3066_PLL_RATE(1200000000, 1, 50, 1),
+	RK3066_PLL_RATE(1176000000, 1, 49, 1),
+	RK3066_PLL_RATE(1128000000, 1, 47, 1),
+	RK3066_PLL_RATE(1104000000, 1, 46, 1),
+	RK3066_PLL_RATE(1008000000, 1, 84, 2),
+	RK3066_PLL_RATE( 912000000, 1, 76, 2),
+	RK3066_PLL_RATE( 888000000, 1, 74, 2),
+	RK3066_PLL_RATE( 816000000, 1, 68, 2),
+	RK3066_PLL_RATE( 792000000, 1, 66, 2),
+	RK3066_PLL_RATE( 696000000, 1, 58, 2),
+	RK3066_PLL_RATE( 672000000, 1, 56, 2),
+	RK3066_PLL_RATE( 648000000, 1, 54, 2),
+	RK3066_PLL_RATE( 624000000, 1, 52, 2),
+	RK3066_PLL_RATE( 600000000, 1, 50, 2),
+	RK3066_PLL_RATE( 576000000, 1, 48, 2),
+	RK3066_PLL_RATE( 552000000, 1, 46, 2),
+	RK3066_PLL_RATE( 528000000, 1, 88, 4),
+	RK3066_PLL_RATE( 504000000, 1, 84, 4),
+	RK3066_PLL_RATE( 480000000, 1, 80, 4),
+	RK3066_PLL_RATE( 456000000, 1, 76, 4),
+	RK3066_PLL_RATE( 408000000, 1, 68, 4),
+	RK3066_PLL_RATE( 312000000, 1, 52, 4),
+	RK3066_PLL_RATE( 252000000, 1, 84, 8),
+	RK3066_PLL_RATE( 216000000, 1, 72, 8),
+	RK3066_PLL_RATE( 126000000, 2, 84, 8),
+	RK3066_PLL_RATE(  48000000, 2, 32, 8),
+	{ /* sentinel */ },
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
+PNAME(mux_armclkb_p)		= { "apllb_core", "gpllb_core" };
+PNAME(mux_armclkl_p)		= { "aplll_core", "gplll_core" };
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_cs_src_p)		= { "apllb_cs", "aplll_cs", "gpll_cs"};
+PNAME(mux_aclk_bus_src_p)	= { "cpll_aclk_bus", "gpll_aclk_bus" };
+
+PNAME(mux_pll_src_cpll_gpll_p)		= { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)	= { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)	= { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_usb_p)	= { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_usb_p)	= { "cpll", "gpll", "usbphy_480m",
+					    "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_npll_p)	= { "cpll", "gpll", "usbphy_480m",
+					    "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_npll_p) = { "cpll", "gpll", "npll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_usb_p) = { "cpll", "gpll", "npll",
+					    "usbphy_480m" };
+
+PNAME(mux_i2s_8ch_pre_p)	= { "i2s_8ch_src", "i2s_8ch_frac",
+				    "ext_i2s", "xin12m" };
+PNAME(mux_i2s_8ch_clkout_p)	= { "i2s_8ch_pre", "xin12m" };
+PNAME(mux_i2s_2ch_p)		= { "i2s_2ch_src", "i2s_2ch_frac",
+				    "dummy", "xin12m" };
+PNAME(mux_spdif_8ch_p)		= { "spdif_8ch_pre", "spdif_8ch_frac",
+				    "ext_i2s", "xin12m" };
+PNAME(mux_edp_24m_p)		= { "dummy", "xin24m" };
+PNAME(mux_vip_out_p)		= { "vip_src", "xin24m" };
+PNAME(mux_usbphy480m_p)		= { "usbotg_out", "xin24m" };
+PNAME(mux_hsic_usbphy480m_p)	= { "usbotg_out", "dummy" };
+PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "xin24m" };
+PNAME(mux_uart3_p)		= { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p)		= { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_mac_p)		= { "mac_pll_src", "ext_gmac" };
+PNAME(mux_mmc_src_p)		= { "cpll", "gpll", "usbphy_480m", "xin24m" };
+
+static struct rockchip_pll_clock rk3368_pll_clks[] __initdata = {
+	[apllb] = PLL(pll_rk3066, PLL_APLLB, "apllb", mux_pll_p, 0, RK3368_PLL_CON(0),
+		     RK3368_PLL_CON(3), 8, 1, 0, rk3368_pll_rates),
+	[aplll] = PLL(pll_rk3066, PLL_APLLL, "aplll", mux_pll_p, 0, RK3368_PLL_CON(4),
+		     RK3368_PLL_CON(7), 8, 0, 0, rk3368_pll_rates),
+	[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3368_PLL_CON(8),
+		     RK3368_PLL_CON(11), 8, 2, 0, NULL),
+	[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3368_PLL_CON(12),
+		     RK3368_PLL_CON(15), 8, 3, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+	[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3368_PLL_CON(16),
+		     RK3368_PLL_CON(19), 8, 4, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+	[npll] = PLL(pll_rk3066, PLL_NPLL, "npll",  mux_pll_p, 0, RK3368_PLL_CON(20),
+		     RK3368_PLL_CON(23), 8, 5, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+};
+
+static struct clk_div_table div_ddrphy_t[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 3, .div = 4 },
+	{ /* sentinel */ },
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
+	.core_reg = RK3368_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 15,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
+	.core_reg = RK3368_CLKSEL_CON(2),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 7,
+};
+
+#define RK3368_DIV_ACLKM_MASK		0x1f
+#define RK3368_DIV_ACLKM_SHIFT		8
+#define RK3368_DIV_ATCLK_MASK		0x1f
+#define RK3368_DIV_ATCLK_SHIFT		0
+#define RK3368_DIV_PCLK_DBG_MASK	0x1f
+#define RK3368_DIV_PCLK_DBG_SHIFT	8
+
+#define RK3368_CLKSEL0(_offs, _aclkm)					\
+	{								\
+		.reg = RK3288_CLKSEL_CON(0 + _offs),			\
+		.val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK,	\
+				RK3368_DIV_ACLKM_SHIFT),		\
+	}
+#define RK3368_CLKSEL1(_offs, _atclk, _pdbg)				\
+	{								\
+		.reg = RK3288_CLKSEL_CON(1 + _offs),			\
+		.val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK,	\
+				RK3368_DIV_ATCLK_SHIFT) |		\
+		       HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK,	\
+				RK3368_DIV_PCLK_DBG_SHIFT),		\
+	}
+
+/* cluster_b: aclkm in clksel0, rest in clksel1 */
+#define RK3368_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3368_CLKSEL0(0, _aclkm),			\
+			RK3368_CLKSEL1(0, _atclk, _pdbg),		\
+		},							\
+	}
+
+/* cluster_l: aclkm in clksel2, rest in clksel3 */
+#define RK3368_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3368_CLKSEL0(2, _aclkm),			\
+			RK3368_CLKSEL1(2, _atclk, _pdbg),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
+	RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
+	RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
+	RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
+	RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
+	RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
+	RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
+	RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
+	RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
+	RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
+	RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
+	RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
+	RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
+	RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
+	RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
+	RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
+	RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
+	RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
+	RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
+	RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
+	RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(13), 8, 1, MFLAGS),
+
+	GATE(0, "apllb_core", "apllb", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 0, GFLAGS),
+	GATE(0, "gpllb_core", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 1, GFLAGS),
+
+	GATE(0, "aplll_core", "aplll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 4, GFLAGS),
+	GATE(0, "gplll_core", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 5, GFLAGS),
+
+	DIV(0, "aclkm_core_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "atclk_core_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "pclk_dbg_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+	DIV(0, "aclkm_core_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "atclk_core_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "pclk_dbg_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+	GATE(0, "apllb_cs", "apllb", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 9, GFLAGS),
+	GATE(0, "aplll_cs", "aplll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 10, GFLAGS),
+	GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NOGATE(0, "sclk_cs_pre", mux_cs_src_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(0, "clkin_trace", "sclk_cs_pre", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(4), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(0), 13, GFLAGS),
+
+	COMPOSITE(0, "aclk_cci_pre", mux_pll_src_cpll_gpll_usb_npll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(0), 12, GFLAGS),
+	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3368_CLKGATE_CON(7), 10, GFLAGS),
+
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", 0,
+			RK3368_CLKGATE_CON(1), 9, GFLAGS),
+	COMPOSITE_NOGATE_DIVTBL(0, "ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(13), 4, 1, MFLAGS, 0, 2, DFLAGS, div_ddrphy_t),
+
+	GATE(0, "sclk_ddr", "ddrphy_div4", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(6), 14, GFLAGS),
+	GATE(0, "sclk_ddr4x", "ddrphy_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(6), 15, GFLAGS),
+
+	GATE(0, "gpll_aclk_bus", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(0, "cpll_aclk_bus", "cpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_bus_src", mux_aclk_bus_src_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 7, 1, MFLAGS, 0, 5, DFLAGS),
+
+	GATE(ACLK_BUS, "aclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_BUS, "pclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 12, 3, DFLAGS,
+			RK3368_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 8, 2, DFLAGS,
+			RK3368_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "sclk_crypto", "aclk_bus_src", 0,
+			RK3368_CLKSEL_CON(10), 14, 2, DFLAGS,
+			RK3368_CLKGATE_CON(7), 2, GFLAGS),
+
+	COMPOSITE(0, "fclk_mcu_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(1), 3, GFLAGS),
+	/*
+	 * stclk_mcu is listed as child of fclk_mcu_src in diagram 5,
+	 * but stclk_mcu has an additional own divider in diagram 2
+	 */
+	COMPOSITE_NOMUX(0, "stclk_mcu", "fclk_mcu_src", 0,
+			RK3368_CLKSEL_CON(12), 8, 3, DFLAGS,
+			RK3368_CLKGATE_CON(13), 13, GFLAGS),
+
+	COMPOSITE(0, "i2s_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(27), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(6), 1, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_8ch_frac", "i2s_8ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(28), 0,
+			RK3368_CLKGATE_CON(6), 2, GFLAGS),
+	MUX(0, "i2s_8ch_pre", mux_i2s_8ch_pre_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(27), 8, 2, MFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "i2s_8ch_clkout", mux_i2s_8ch_clkout_p, 0,
+			RK3368_CLKSEL_CON(27), 15, 1, MFLAGS,
+			RK3368_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(SCLK_I2S_8CH, "sclk_i2s_8ch", "i2s_8ch_pre", CLK_SET_RATE_PARENT,
+			RK3368_CLKGATE_CON(6), 3, GFLAGS),
+	COMPOSITE(0, "spdif_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(31), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(6), 4, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(32), 0,
+			RK3368_CLKGATE_CON(6), 5, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+			RK3368_CLKSEL_CON(31), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(6), 6, GFLAGS),
+	COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(53), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(5), 13, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(54), 0,
+			RK3368_CLKGATE_CON(5), 14, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, 0,
+			RK3368_CLKSEL_CON(53), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(5), 15, GFLAGS),
+
+	COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3368_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(0, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0,
+			RK3368_CLKGATE_CON(13), 7, GFLAGS),
+
+	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(35), 12, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(37), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 4, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(37), 8, 1, MFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 6, GFLAGS),
+	COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 7, GFLAGS),
+
+	/*
+	 * We introduce a virtual node of hclk_vodec_pre_v to split one clock
+	 * struct with a gate and a fix divider into two node in software.
+	 */
+	GATE(0, "hclk_video_pre_v", "aclk_vdpu", 0,
+		RK3368_CLKGATE_CON(4), 8, GFLAGS),
+
+	COMPOSITE(0, "sclk_hevc_cabac_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+			RK3368_CLKSEL_CON(17), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 1, GFLAGS),
+	COMPOSITE(0, "sclk_hevc_core_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+			RK3368_CLKSEL_CON(17), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 2, GFLAGS),
+
+	COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(19), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 0, GFLAGS),
+	DIV(0, "hclk_vio", "aclk_vio0", 0,
+			RK3368_CLKSEL_CON(21), 0, 5, DFLAGS),
+
+	COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(18), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 3, GFLAGS),
+	COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(18), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 4, GFLAGS),
+
+	COMPOSITE(DCLK_VOP, "dclk_vop", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3368_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3368_CLKGATE_CON(4), 1, GFLAGS),
+
+	GATE(SCLK_VOP0_PWM, "sclk_vop0_pwm", "xin24m", 0,
+			RK3368_CLKGATE_CON(4), 2, GFLAGS),
+
+	COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(22), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(4), 9, GFLAGS),
+
+	GATE(0, "pclk_isp_in", "ext_isp", 0,
+			RK3368_CLKGATE_CON(17), 2, GFLAGS),
+	INVERTER(PCLK_ISP, "pclk_isp", "pclk_isp_in",
+			RK3368_CLKSEL_CON(21), 6, IFLAGS),
+
+	GATE(0, "pclk_vip_in", "ext_vip", 0,
+			RK3368_CLKGATE_CON(16), 13, GFLAGS),
+	INVERTER(PCLK_VIP, "pclk_vip", "pclk_vip_in",
+			RK3368_CLKSEL_CON(21), 13, IFLAGS),
+
+	GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
+			RK3368_CLKGATE_CON(4), 13, GFLAGS),
+	GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
+			RK3368_CLKGATE_CON(5), 12, GFLAGS),
+
+	COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
+			RK3368_CLKGATE_CON(4), 5, GFLAGS),
+	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
+			RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS),
+
+	COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
+			RK3368_CLKSEL_CON(23), 8, 1, MFLAGS,
+			RK3368_CLKGATE_CON(5), 4, GFLAGS),
+	COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(23), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(5), 3, GFLAGS),
+
+	COMPOSITE(SCLK_HDCP, "sclk_hdcp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(5), 5, GFLAGS),
+
+	DIV(0, "pclk_pd_alive", "gpll", 0,
+			RK3368_CLKSEL_CON(10), 8, 5, DFLAGS),
+
+	/* sclk_timer has a gate in the sgrf */
+
+	COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(10), 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(7), 9, GFLAGS),
+	GATE(SCLK_PVTM_PMU, "sclk_pvtm_pmu", "xin24m", 0,
+			RK3368_CLKGATE_CON(7), 3, GFLAGS),
+	COMPOSITE(0, "sclk_gpu_core_src", mux_pll_src_cpll_gpll_usb_npll_p, 0,
+			RK3368_CLKSEL_CON(14), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 11, GFLAGS),
+	MUX(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(14), 14, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_gpu_mem_pre", "aclk_gpu_src", 0,
+			RK3368_CLKSEL_CON(14), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_gpu_cfg_pre", "aclk_gpu_src", 0,
+			RK3368_CLKSEL_CON(16), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0,
+			RK3368_CLKGATE_CON(7), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(9), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(3), 0, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+			RK3368_CLKSEL_CON(9), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3368_CLKGATE_CON(3), 3, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(9), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3368_CLKGATE_CON(3), 2, GFLAGS),
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(3), 1, GFLAGS),
+
+	GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3368_CLKGATE_CON(4), 14, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+
+	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(45), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 7, GFLAGS),
+	COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(45), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(46), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 9, GFLAGS),
+
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 12, GFLAGS),
+	COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(48), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 13, GFLAGS),
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(51), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 15, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3368_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3368_SDMMC_CON1, 0),
+
+	MMC(SCLK_SDIO0_DRV,    "sdio0_drv",    "sclk_sdio0", RK3368_SDIO0_CON0, 1),
+	MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3368_SDIO0_CON1, 0),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3368_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3368_EMMC_CON1,  0),
+
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(8), 1, GFLAGS),
+
+	/* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(8), 4, GFLAGS),
+
+	/* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+	COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+			RK3368_CLKSEL_CON(25), 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(3), 5, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+			RK3368_CLKSEL_CON(25), 8, 8, DFLAGS,
+			RK3368_CLKGATE_CON(3), 6, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(7), 8, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(52), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(6), 7, GFLAGS),
+
+	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb_usb_p, 0,
+			RK3368_CLKSEL_CON(33), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(34), 0,
+			RK3368_CLKGATE_CON(2), 1, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(33), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(35), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 2, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(36), 0,
+			RK3368_CLKGATE_CON(2), 3, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(35), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(39), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 6, GFLAGS),
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(40), 0,
+			RK3368_CLKGATE_CON(2), 7, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(39), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(41), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 8, GFLAGS),
+	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(42), 0,
+			RK3368_CLKGATE_CON(2), 9, GFLAGS),
+	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(41), 8, 2, MFLAGS),
+
+	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(43), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(3), 4, GFLAGS),
+	MUX(SCLK_MAC, "mac_clk", mux_mac_p, 0,
+			RK3368_CLKSEL_CON(43), 8, 1, MFLAGS),
+	GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(SCLK_MACREF, "sclk_macref", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(SCLK_MAC_RX, "sclk_mac_rx", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 4, GFLAGS),
+	GATE(SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 5, GFLAGS),
+
+	GATE(0, "jtag", "ext_jtag", 0,
+			RK3368_CLKGATE_CON(7), 0, GFLAGS),
+
+	COMPOSITE_NODIV(0, "hsic_usbphy_480m", mux_hsic_usbphy480m_p, 0,
+			RK3368_CLKSEL_CON(26), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(8), 0, GFLAGS),
+	COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+			RK3368_CLKSEL_CON(26), 12, 2, MFLAGS,
+			RK3368_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(SCLK_HSICPHY12M, "sclk_hsicphy12m", "xin12m", 0,
+			RK3368_CLKGATE_CON(8), 6, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 5
+	 */
+
+	/* aclk_cci_pre gates */
+	GATE(0, "aclk_core_niu_cpup", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 4, GFLAGS),
+	GATE(0, "aclk_core_niu_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 3, GFLAGS),
+	GATE(0, "aclk_cci400", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 2, GFLAGS),
+	GATE(0, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 1, GFLAGS),
+	GATE(0, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 0, GFLAGS),
+
+	/* aclkm_core_* gates */
+	GATE(0, "aclk_adb400s_pd_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(0, "aclk_adb400s_pd_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 0, GFLAGS),
+
+	/* armclk* gates */
+	GATE(0, "sclk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(0, "sclk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 1, GFLAGS),
+
+	/* sclk_cs_pre gates */
+	GATE(0, "sclk_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 7, GFLAGS),
+	GATE(0, "pclk_core_niu_sdbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 6, GFLAGS),
+	GATE(0, "hclk_core_niu_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 5, GFLAGS),
+
+	/* aclk_bus gates */
+	GATE(0, "aclk_strc_sys", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 12, GFLAGS),
+	GATE(ACLK_DMAC_BUS, "aclk_dmac_bus", "aclk_bus", 0, RK3368_CLKGATE_CON(12), 11, GFLAGS),
+	GATE(0, "sclk_intmem1", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 6, GFLAGS),
+	GATE(0, "sclk_intmem0", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 5, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 4, GFLAGS),
+	GATE(0, "aclk_gic400", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 9, GFLAGS),
+
+	/* sclk_ddr gates */
+	GATE(0, "nclk_ddrupctl", "sclk_ddr", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 2, GFLAGS),
+
+	/* clk_hsadc_tsp is part of diagram2 */
+
+	/* fclk_mcu_src gates */
+	GATE(0, "hclk_noc_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 14, GFLAGS),
+	GATE(0, "fclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 12, GFLAGS),
+	GATE(0, "hclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 10, GFLAGS),
+	GATE(HCLK_ROM, "hclk_rom", "hclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 9, GFLAGS),
+	GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 8, GFLAGS),
+	GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 7, GFLAGS),
+	GATE(HCLK_TSP, "hclk_tsp", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 10, GFLAGS),
+	GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 4, GFLAGS),
+	GATE(MCLK_CRYPTO, "mclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 3, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 14, GFLAGS),
+	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 13, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 3, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 2, GFLAGS),
+	GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 1, GFLAGS),
+	GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 0, GFLAGS),
+	GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS),
+	GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS),
+	GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS),
+
+	/*
+	 * video clk gates
+	 * aclk_video(_pre) can actually select between parents of aclk_vdpu
+	 * and aclk_vepu by setting bit GRF_SOC_CON0[7].
+	 */
+	GATE(ACLK_VIDEO, "aclk_video", "aclk_vdpu", 0, RK3368_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", "sclk_hevc_cabac_src", 0, RK3368_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(SCLK_HEVC_CORE, "sclk_hevc_core", "sclk_hevc_core_src", 0, RK3368_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(HCLK_VIDEO, "hclk_video", "hclk_video_pre", 0, RK3368_CLKGATE_CON(15), 1, GFLAGS),
+
+	/* aclk_rga_pre gates */
+	GATE(ACLK_VIO1_NOC, "aclk_vio1_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 10, GFLAGS),
+	GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(16), 0, GFLAGS),
+	GATE(ACLK_HDCP, "aclk_hdcp", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(17), 10, GFLAGS),
+
+	/* aclk_vio0 gates */
+	GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 11, GFLAGS),
+	GATE(ACLK_VIO0_NOC, "aclk_vio0_noc", "aclk_vio0", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 9, GFLAGS),
+	GATE(ACLK_VOP, "aclk_vop", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 5, GFLAGS),
+	GATE(ACLK_VOP_IEP, "aclk_vop_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 4, GFLAGS),
+	GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 2, GFLAGS),
+
+	/* sclk_isp gates */
+	GATE(HCLK_ISP, "hclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(16), 14, GFLAGS),
+	GATE(ACLK_ISP, "aclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+
+	/* hclk_vio gates */
+	GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 12, GFLAGS),
+	GATE(HCLK_VIO_NOC, "hclk_vio_noc", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 8, GFLAGS),
+	GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 7, GFLAGS),
+	GATE(HCLK_VOP, "hclk_vop", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 6, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 3, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 1, GFLAGS),
+	GATE(HCLK_VIO_HDCPMMU, "hclk_hdcpmmu", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 12, GFLAGS),
+	GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 7, GFLAGS),
+
+	/*
+	 * pclk_vio gates
+	 * pclk_vio comes from the exactly same source as hclk_vio
+	 */
+	GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 11, GFLAGS),
+	GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 9, GFLAGS),
+	GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 8, GFLAGS),
+	GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 6, GFLAGS),
+	GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+	GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+
+	/* ext_vip gates in diagram3 */
+
+	/* gpu gates */
+	GATE(SCLK_GPU_CORE, "sclk_gpu_core", "sclk_gpu_core_src", 0, RK3368_CLKGATE_CON(18), 2, GFLAGS),
+	GATE(ACLK_GPU_MEM, "aclk_gpu_mem", "aclk_gpu_mem_pre", 0, RK3368_CLKGATE_CON(18), 1, GFLAGS),
+	GATE(ACLK_GPU_CFG, "aclk_gpu_cfg", "aclk_gpu_cfg_pre", 0, RK3368_CLKGATE_CON(18), 0, GFLAGS),
+
+	/* aclk_peri gates */
+	GATE(ACLK_DMAC_PERI, "aclk_dmac_peri", "aclk_peri", 0, RK3368_CLKGATE_CON(19), 3, GFLAGS),
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 2, GFLAGS),
+	GATE(HCLK_SFC, "hclk_sfc", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 15, GFLAGS),
+	GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 13, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 8, GFLAGS),
+	GATE(ACLK_PERI_MMU, "aclk_peri_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(21), 4, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 0, GFLAGS),
+	GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 11, GFLAGS),
+	GATE(0, "hclk_mmc_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 10, GFLAGS),
+	GATE(0, "hclk_emem_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 9, GFLAGS),
+	GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 7, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 6, GFLAGS),
+	GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 5, GFLAGS),
+	GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 4, GFLAGS),
+	GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 3, GFLAGS),
+	GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 2, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 1, GFLAGS),
+	GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 3, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 2, GFLAGS),
+	GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 1, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 0, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 15, GFLAGS),
+	GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 14, GFLAGS),
+	GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 13, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 12, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 11, GFLAGS),
+	GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 10, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 9, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 8, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 7, GFLAGS),
+	GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 6, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 5, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 4, GFLAGS),
+	GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 1, GFLAGS),
+	GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 14, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS),
+
+	/* pclk_pd_alive gates */
+	GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS),
+	GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS),
+
+	/*
+	 * pclk_vio gates
+	 * pclk_vio comes from the exactly same source as hclk_vio
+	 */
+	GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+
+	/* pclk_pd_pmu gates */
+	GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+	GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+	GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+	GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS),
+	GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+
+	/* timer gates */
+	GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
+	GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
+	GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
+	GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
+	GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
+	GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
+	GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
+	GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
+	GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
+	GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
+	GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
+	GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
+};
+
+static void __init rk3368_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "ddrphy_div4", "ddrphy_src", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_video_pre",
+					"hclk_video_pre_v", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	/* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
+	clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+			__func__, PTR_ERR(clk));
+	else
+		rockchip_clk_add_lookup(clk, PCLK_WDT);
+
+	rockchip_clk_register_plls(rk3368_pll_clks,
+				   ARRAY_SIZE(rk3368_pll_clks),
+				   RK3368_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(rk3368_clk_branches,
+				  ARRAY_SIZE(rk3368_clk_branches));
+
+	rockchip_clk_register_armclk(ARMCLKB, "armclkb",
+			mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+			&rk3368_cpuclkb_data, rk3368_cpuclkb_rates,
+			ARRAY_SIZE(rk3368_cpuclkb_rates));
+
+	rockchip_clk_register_armclk(ARMCLKL, "armclkl",
+			mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+			&rk3368_cpuclkl_data, rk3368_cpuclkl_rates,
+			ARRAY_SIZE(rk3368_cpuclkl_rates));
+
+	rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
+}
+CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index b72dad0..f506df8 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -57,6 +57,22 @@
 #define RK3288_EMMC_CON0		0x218
 #define RK3288_EMMC_CON1		0x21c
 
+#define RK3368_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3368_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
+#define RK3368_CLKGATE_CON(x)		((x) * 0x4 + 0x200)
+#define RK3368_GLB_SRST_FST		0x280
+#define RK3368_GLB_SRST_SND		0x284
+#define RK3368_SOFTRST_CON(x)		((x) * 0x4 + 0x300)
+#define RK3368_MISC_CON			0x380
+#define RK3368_SDMMC_CON0		0x400
+#define RK3368_SDMMC_CON1		0x404
+#define RK3368_SDIO0_CON0		0x408
+#define RK3368_SDIO0_CON1		0x40c
+#define RK3368_SDIO1_CON0		0x410
+#define RK3368_SDIO1_CON1		0x414
+#define RK3368_EMMC_CON0		0x418
+#define RK3368_EMMC_CON1		0x41c
+
 enum rockchip_pll_type {
 	pll_rk3066,
 };
-- 
2.1.4



From heiko at sntech.de  Sat Jun 13 14:02:14 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Sat, 13 Jun 2015 23:02:14 +0200
Subject: [PATCH v6 0/3] ARM: rockchip: fix the SMP
In-Reply-To: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
References: <1433843400-24831-1-git-send-email-wxt@rock-chips.com>
Message-ID: <3561257.px5A2HfJ0t@diego>

Hi Caesar,

Am Dienstag, 9. Juni 2015, 17:49:56 schrieb Caesar Wang:
> Verified on url =
>    
> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-> 3.14 Tested by 179200 cycles are pass with CPU up/dowm test scripts.

I've applied this series to my soc branch for 4.3 ... it's a bit late for 
trying to cram this into 4.2. I've also added a Cc stable@ tag for patch1


Heiko


From sasukewxt at 163.com  Sat Jun 13 20:15:34 2015
From: sasukewxt at 163.com (Caesar Wang)
Date: Sun, 14 Jun 2015 11:15:34 +0800
Subject: [PATCH v14 2/3] power-domain: rockchip: add power domain driver
In-Reply-To: <CAPDyKFrBzZjOVZzq9unQQwm2BSA0kzeT7EE8_kSpH_udMKjo6A@mail.gmail.com>
References: <1429862868-14218-1-git-send-email-wxt@rock-chips.com>
 <1429862868-14218-3-git-send-email-wxt@rock-chips.com>
 <CAPDyKFrBzZjOVZzq9unQQwm2BSA0kzeT7EE8_kSpH_udMKjo6A@mail.gmail.com>
Message-ID: <557CF1D6.4090506@163.com>

Ulf,

Thanks for your comments.:-)



? 2015?05?28? 18:38, Ulf Hansson ??:
> On 24 April 2015 at 10:07, Caesar Wang <wxt at rock-chips.com> wrote:
>> In order to meet high performance and low power requirements, a power
>> management unit is designed or saving power when RK3288 in low power
>> mode.
>> The RK3288 PMU is dedicated for managing the power ot the whole chip.
>>
>> Signed-off-by: jinkun.hong <jinkun.hong at rock-chips.com>
>> Signed-off-by: Caesar Wang <wxt at rock-chips.com>
>> ---
>>
>>   arch/arm/mach-rockchip/Kconfig      |   1 +
>>   arch/arm/mach-rockchip/Makefile     |   1 +
>>   arch/arm/mach-rockchip/pm_domains.c | 506 ++++++++++++++++++++++++++++++++++++
>>   3 files changed, 508 insertions(+)
>>   create mode 100644 arch/arm/mach-rockchip/pm_domains.c
>>
>> diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
>> index ae4eb7c..578206b 100644
>> --- a/arch/arm/mach-rockchip/Kconfig
>> +++ b/arch/arm/mach-rockchip/Kconfig
>> @@ -15,6 +15,7 @@ config ARCH_ROCKCHIP
>>          select ROCKCHIP_TIMER
>>          select ARM_GLOBAL_TIMER
>>          select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
>> +       select PM_GENERIC_DOMAINS if PM
>>          help
>>            Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs
>>            containing the RK2928, RK30xx and RK31xx series.
>> diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
>> index 5c3a9b2..9c902d3 100644
>> --- a/arch/arm/mach-rockchip/Makefile
>> +++ b/arch/arm/mach-rockchip/Makefile
>> @@ -1,5 +1,6 @@
>>   CFLAGS_platsmp.o := -march=armv7-a
>>
>>   obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o
>> +obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
>>   obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o
>>   obj-$(CONFIG_SMP) += headsmp.o platsmp.o
>> diff --git a/arch/arm/mach-rockchip/pm_domains.c b/arch/arm/mach-rockchip/pm_domains.c
>> new file mode 100644
>> index 0000000..92d2569
>> --- /dev/null
>> +++ b/arch/arm/mach-rockchip/pm_domains.c
>> @@ -0,0 +1,506 @@
>> +/*
>> + * Rockchip Generic power domain support.
>> + *
>> + * Copyright (c) 2014 ROCKCHIP, Co. 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 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +#include <linux/pm_clock.h>
>> +#include <linux/pm_domain.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/clk.h>
>> +#include <linux/clk-provider.h>
> clk-provider.h, why?

The following is needed.

_clk_get_name(clk)


>
>> +#include <linux/regmap.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <dt-bindings/power-domain/rk3288.h>
> Same comment as in patch1. I don't find this header.

OK.
Perhaps, Making a mistake. the missing the patch in 
here.(https://patchwork.kernel.org/patch/6266881/)
>> +
>> +struct rockchip_domain_info {
>> +       int pwr_mask;
>> +       int status_mask;
>> +       int req_mask;
>> +       int idle_mask;
>> +       int ack_mask;
>> +};
>> +
>> +struct rockchip_pmu_info {
>> +       u32 pwr_offset;
>> +       u32 status_offset;
>> +       u32 req_offset;
>> +       u32 idle_offset;
>> +       u32 ack_offset;
>> +
>> +       u32 core_pwrcnt_offset;
>> +       u32 gpu_pwrcnt_offset;
>> +
>> +       unsigned int core_power_transition_time;
>> +       unsigned int gpu_power_transition_time;
>> +
>> +       int num_domains;
>> +       const struct rockchip_domain_info *domain_info;
>> +};
>> +
>> +struct rockchip_pm_domain {
>> +       struct generic_pm_domain genpd;
>> +       const struct rockchip_domain_info *info;
>> +       struct rockchip_pmu *pmu;
>> +       int num_clks;
>> +       struct clk *clks[];
>> +};
>> +
>> +struct rockchip_pmu {
>> +       struct device *dev;
>> +       struct regmap *regmap;
>> +       const struct rockchip_pmu_info *info;
>> +       struct mutex mutex; /* mutex lock for pmu */
>> +       struct genpd_onecell_data genpd_data;
>> +       struct generic_pm_domain *domains[];
>> +};
>> +
>> +#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
>> +
>> +#define DOMAIN(pwr, status, req, idle, ack)    \
>> +{                                              \
>> +       .pwr_mask = BIT(pwr),                   \
>> +       .status_mask = BIT(status),             \
>> +       .req_mask = BIT(req),                   \
>> +       .idle_mask = BIT(idle),                 \
>> +       .ack_mask = BIT(ack),                   \
>> +}
>> +
>> +#define DOMAIN_RK3288(pwr, status, req)                \
>> +       DOMAIN(pwr, status, req, req, (req) + 16)
>> +
>> +static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
>> +{
>> +       struct rockchip_pmu *pmu = pd->pmu;
>> +       const struct rockchip_domain_info *pd_info = pd->info;
>> +       unsigned int val;
>> +
>> +       regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
>> +       return (val & pd_info->idle_mask) == pd_info->idle_mask;
>> +}
>> +
>> +static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
>> +                                        bool idle)
>> +{
>> +       const struct rockchip_domain_info *pd_info = pd->info;
>> +       struct rockchip_pmu *pmu = pd->pmu;
>> +       unsigned int val;
>> +
>> +       regmap_update_bits(pmu->regmap, pmu->info->req_offset,
>> +                          pd_info->req_mask, idle ? -1U : 0);
>> +
>> +       dsb();
>> +
>> +       do {
>> +               regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
>> +       } while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0));
>> +
>> +       while (rockchip_pmu_domain_is_idle(pd) != idle)
>> +               cpu_relax();
>> +
>> +       return 0;
>> +}
>> +
>> +static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
>> +{
>> +       struct rockchip_pmu *pmu = pd->pmu;
>> +       unsigned int val;
>> +
>> +       regmap_read(pmu->regmap, pmu->info->status_offset, &val);
>> +
>> +       /* 1'b0: power on, 1'b1: power off */
>> +       return !(val & pd->info->status_mask);
>> +}
>> +
>> +static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
>> +                                            bool on)
>> +{
>> +       struct rockchip_pmu *pmu = pd->pmu;
>> +
>> +       regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
>> +                          pd->info->pwr_mask, on ? 0 : -1U);
>> +
>> +       dsb();
>> +
>> +       while (rockchip_pmu_domain_is_on(pd) != on)
>> +               cpu_relax();
>> +}
>> +
>> +static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
>> +{
>> +       int i;
>> +
>> +       mutex_lock(&pd->pmu->mutex);
> I don't quite understand why you need a lock, what are you protecting and why?

Says:
[ 3551.678762] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3551.899180] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3551.905958] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3551.912832] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3551.919730] rockchip_pd_power:139: mutex_lock
[ 3551.924130] rockchip_pd_power:167,mutex_unlock
[ 3563.827295] rockchip_pd_power:139: mutex_lock
[ 3563.831753] rockchip_pd_power:167,mutex_unlock
[ 3563.836216] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3564.058989] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3564.065659] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3564.072354] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3564.079047] rockchip_pd_power:139: mutex_lock
[ 3564.083426] rockchip_pd_power:167,mutex_unlock
[ 3611.665726] rockchip_pd_power:139: mutex_lock
[ 3611.670206] rockchip_pd_power:167,mutex_unlock
[ 3611.674692] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3611.899160] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3611.905938] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
[ 3611.912818] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
[ 3611.919689] rockchip_pd_power:139: mutex_lock
[ 3611.924090] rockchip_pd_power:167,mutex_unlock
[ 3623.848296] rockchip_pd_power:139: mutex_lock
[ 3623.852752] rockchip_pd_power:167,mutex_unlock



>> +
>> +       if (rockchip_pmu_domain_is_on(pd) != power_on) {
>> +               for (i = 0; i < pd->num_clks; i++)
>> +                       clk_enable(pd->clks[i]);
>> +
>> +               if (!power_on) {
>> +                       /* FIXME: add code to save AXI_QOS */
>> +
>> +                       /* if powering down, idle request to NIU first */
>> +                       rockchip_pmu_set_idle_request(pd, true);
>> +               }
>> +
>> +               rockchip_do_pmu_set_power_domain(pd, power_on);
>> +
>> +               if (power_on) {
>> +                       /* if powering up, leave idle mode */
>> +                       rockchip_pmu_set_idle_request(pd, false);
>> +
>> +                       /* FIXME: add code to restore AXI_QOS */
>> +               }
>> +
>> +               for (i = pd->num_clks - 1; i >= 0; i--)
>> +                       clk_disable(pd->clks[i]);
>> +       }
>> +
>> +       mutex_unlock(&pd->pmu->mutex);
>> +       return 0;
>> +}
>> +
>> +static int rockchip_pd_power_on(struct generic_pm_domain *domain)
>> +{
>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>> +
>> +       return rockchip_pd_power(pd, true);
>> +}
>> +
>> +static int rockchip_pd_power_off(struct generic_pm_domain *domain)
>> +{
>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>> +
>> +       return rockchip_pd_power(pd, false);
>> +}
>> +
>> +static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
>> +                                 struct device *dev)
>> +{
>> +       struct clk *clk;
>> +       int i;
>> +       int error;
>> +
>> +       dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
>> +
>> +       error = pm_clk_create(dev);
>> +       if (error) {
>> +               dev_err(dev, "pm_clk_create failed %d\n", error);
>> +               return error;
>> +       }
>> +
>> +       i = 0;
>> +       while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
> This loop adds all available device clocks to the PM clock list. I
> wonder if this could be considered as a common thing and if so, we
> might want to extend the pm_clk API with this.

There are several reasons as follows:

     Firstly, the clocks need be turned off to save power when
     the system enter the suspend state. So we need to enumerate the clocks
     in the dts. In order to power domain can turn on and off.

     Secondly, the reset-circuit should reset be synchronous on rk3288, 
then sync revoked.
     So we need to enable clocks of all devices.
>> +               dev_dbg(dev, "adding clock '%s' to list of PM clocks\n",
>> +                       __clk_get_name(clk));
>> +               error = pm_clk_add_clk(dev, clk);
>> +               clk_put(clk);
>> +               if (error) {
>> +                       dev_err(dev, "pm_clk_add_clk failed %d\n", error);
>> +                       pm_clk_destroy(dev);
>> +                       return error;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
>> +                                  struct device *dev)
>> +{
>> +       dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
>> +
>> +       pm_clk_destroy(dev);
>> +}
>> +
>> +static int rockchip_pd_start_dev(struct device *dev)
>> +{
>> +       struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
>> +
>> +       dev_dbg(dev, "starting device in power domain '%s'\n", genpd->name);
>> +
>> +       return pm_clk_resume(dev);
>> +}
>> +
>> +static int rockchip_pd_stop_dev(struct device *dev)
>> +{
>> +       struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
>> +
>> +       dev_dbg(dev, "stopping device in power domain '%s'\n", genpd->name);
>> +
>> +       return pm_clk_suspend(dev);
>> +}
>> +
>> +static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
>> +                                     struct device_node *node)
>> +{
>> +       const struct rockchip_domain_info *pd_info;
>> +       struct rockchip_pm_domain *pd;
>> +       struct clk *clk;
>> +       int clk_cnt;
>> +       int i;
>> +       u32 id;
>> +       int error;
>> +
>> +       error = of_property_read_u32(node, "reg", &id);
>> +       if (error) {
>> +               dev_err(pmu->dev,
>> +                       "%s: failed to retrieve domain id (reg): %d\n",
>> +                       node->name, error);
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (id >= pmu->info->num_domains) {
>> +               dev_err(pmu->dev, "%s: invalid domain id %d\n",
>> +                       node->name, id);
>> +               return -EINVAL;
>> +       }
>> +
>> +       pd_info = &pmu->info->domain_info[id];
>> +       if (!pd_info) {
>> +               dev_err(pmu->dev, "%s: undefined domain id %d\n",
>> +                       node->name, id);
>> +               return -EINVAL;
>> +       }
>> +
>> +       clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
>> +       pd = devm_kzalloc(pmu->dev,
>> +                         sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
>> +                         GFP_KERNEL);
>> +       if (!pd)
>> +               return -ENOMEM;
>> +
>> +       pd->info = pd_info;
>> +       pd->pmu = pmu;
>> +
>> +       for (i = 0; i < clk_cnt; i++) {
> This loop is similar to the one when creates the PM clock list in the
> rockchip_pd_attach_dev().
>
> What's the reason you don't want to use pm clk for these clocks?
>

Ditto.
>> +               clk = of_clk_get(node, i);
>> +               if (IS_ERR(clk)) {
>> +                       error = PTR_ERR(clk);
>> +                       dev_err(pmu->dev,
>> +                               "%s: failed to get clk %s (index %d): %d\n",
>> +                               node->name, __clk_get_name(clk), i, error);
>> +                       goto err_out;
>> +               }
>> +
>> +               error = clk_prepare(clk);
>> +               if (error) {
>> +                       dev_err(pmu->dev,
>> +                               "%s: failed to prepare clk %s (index %d): %d\n",
>> +                               node->name, __clk_get_name(clk), i, error);
>> +                       clk_put(clk);
>> +                       goto err_out;
>> +               }
>> +
>> +               pd->clks[pd->num_clks++] = clk;
>> +
>> +               dev_dbg(pmu->dev, "added clock '%s' to domain '%s'\n",
>> +                       __clk_get_name(clk), node->name);
>> +       }
>> +
>> +       error = rockchip_pd_power(pd, true);
>> +       if (error) {
>> +               dev_err(pmu->dev,
>> +                       "failed to power on domain '%s': %d\n",
>> +                       node->name, error);
>> +               goto err_out;
>> +       }
>> +
>> +       pd->genpd.name = node->name;
>> +       pd->genpd.power_off = rockchip_pd_power_off;
>> +       pd->genpd.power_on = rockchip_pd_power_on;
>> +       pd->genpd.attach_dev = rockchip_pd_attach_dev;
>> +       pd->genpd.detach_dev = rockchip_pd_detach_dev;
>> +       pd->genpd.dev_ops.start = rockchip_pd_start_dev;
>> +       pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;
> Instead of assigning the ->stop|start() callbacks, which do
> pm_clk_suspend|resume(), just set the genpd->flags to
> GENPD_FLAG_PM_CLK, and genpd will fix this for you.
>
Ditto.

>> +       pm_genpd_init(&pd->genpd, NULL, false);
>> +
>> +       pmu->genpd_data.domains[id] = &pd->genpd;
>> +       return 0;
>> +
>> +err_out:
>> +       while (--i >= 0) {
>> +               clk_unprepare(pd->clks[i]);
>> +               clk_put(pd->clks[i]);
>> +       }
>> +       return error;
>> +}
>> +
>> +static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; i < pd->num_clks; i++) {
>> +               clk_unprepare(pd->clks[i]);
> If you converted these clocks to be dealt with via the PM clk API,
> pm_clk_destoy() would have replaced this loop.
>
>> +               clk_put(pd->clks[i]);
>> +       }
>> +
>> +       /* devm will free our memory */
>> +}
>> +
>> +static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
>> +{
>> +       struct generic_pm_domain *genpd;
>> +       struct rockchip_pm_domain *pd;
>> +       int i;
>> +
>> +       for (i = 0; i < pmu->genpd_data.num_domains; i++) {
>> +               genpd = pmu->genpd_data.domains[i];
>> +               if (genpd) {
>> +                       pd = to_rockchip_pd(genpd);
>> +                       rockchip_pm_remove_one_domain(pd);
>> +               }
>> +       }
>> +
>> +       /* devm will free our memory */
>> +}
>> +
>> +static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
>> +                                     u32 domain_reg_offset,
>> +                                     unsigned int count)
>> +{
>> +       /* First configure domain power down transition count ... */
>> +       regmap_write(pmu->regmap, domain_reg_offset, count);
>> +       /* ... and then power up count. */
>> +       regmap_write(pmu->regmap, domain_reg_offset + 4, count);
>> +}
>> +
>> +static int rockchip_pm_domain_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev = &pdev->dev;
>> +       struct device_node *np = dev->of_node;
>> +       struct device_node *node;
>> +       struct rockchip_pmu *pmu;
>> +       const struct of_device_id *match;
>> +       const struct rockchip_pmu_info *pmu_info;
>> +       int error;
>> +
>> +       if (!np) {
>> +               dev_err(dev, "device tree node not found\n");
>> +               return -ENXIO;/
> Nitpick:
> It's more common to return -ENODEV here, you might want to change.

OK.

Thanks,
Caesar
>> +       }
>> +
>> +       match = of_match_device(dev->driver->of_match_table, dev);
>> +       if (!match || !match->data) {
>> +               dev_err(dev, "missing pmu data\n");
>> +               return -EINVAL;
>> +       }
>> +
>> +       pmu_info = match->data;
>> +
>> +       pmu = devm_kzalloc(dev,
>> +                          sizeof(*pmu) +
>> +                               pmu_info->num_domains * sizeof(pmu->domains[0]),
>> +                          GFP_KERNEL);
>> +       if (!pmu)
>> +               return -ENOMEM;
>> +
>> +       pmu->dev = &pdev->dev;
>> +       mutex_init(&pmu->mutex);
>> +
>> +       pmu->info = pmu_info;
>> +
>> +       pmu->genpd_data.domains = pmu->domains;
>> +       pmu->genpd_data.num_domains = pmu_info->num_domains;
>> +
>> +       node = of_parse_phandle(np, "rockchip,pmu", 0);
>> +       pmu->regmap = syscon_node_to_regmap(node);
>> +       of_node_put(node);
>> +       if (IS_ERR(pmu->regmap)) {
>> +               error = PTR_ERR(pmu->regmap);
>> +               dev_err(dev, "failed to get PMU regmap: %d\n", error);
>> +               return error;
>> +       }
>> +
>> +       /*
>> +        * Configure power up and down transition delays for core
>> +        * and GPU domains.
>> +        */
>> +       rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
>> +                                 pmu_info->core_power_transition_time);
>> +       rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
>> +                                 pmu_info->gpu_power_transition_time);
>> +
>> +       error = -ENXIO;
>> +
>> +       for_each_available_child_of_node(np, node) {
>> +               error = rockchip_pm_add_one_domain(pmu, node);
>> +               if (error) {
>> +                       dev_err(dev, "failed to handle node %s: %d\n",
>> +                               node->name, error);
>> +                       goto err_out;
>> +               }
>> +       }
>> +
>> +       if (error) {
>> +               dev_dbg(dev, "no power domains defined\n");
>> +               goto err_out;
>> +       }
>> +
>> +       of_genpd_add_provider_onecell(np, &pmu->genpd_data);
>> +
>> +       return 0;
>> +
>> +err_out:
>> +       rockchip_pm_domain_cleanup(pmu);
>> +       return error;
>> +}
>> +
>> +static const struct rockchip_domain_info rk3288_pm_domains[] = {
>> +       [RK3288_PD_GPU]         = DOMAIN_RK3288(9, 9, 2),
>> +       [RK3288_PD_VIO]         = DOMAIN_RK3288(7, 7, 4),
>> +       [RK3288_PD_VIDEO]       = DOMAIN_RK3288(8, 8, 3),
>> +       [RK3288_PD_HEVC]        = DOMAIN_RK3288(14, 10, 9),
>> +};
>> +
>> +static const struct rockchip_pmu_info rk3288_pmu = {
>> +       .pwr_offset = 0x08,
>> +       .status_offset = 0x0c,
>> +       .req_offset = 0x10,
>> +       .idle_offset = 0x14,
>> +       .ack_offset = 0x14,
>> +
>> +       .core_pwrcnt_offset = 0x34,
>> +       .gpu_pwrcnt_offset = 0x3c,
>> +
>> +       .core_power_transition_time = 24, /* 1us */
>> +       .gpu_power_transition_time = 24, /* 1us */
>> +
>> +       .num_domains = ARRAY_SIZE(rk3288_pm_domains),
>> +       .domain_info = rk3288_pm_domains,
>> +};
>> +
>> +static const struct of_device_id rockchip_pm_domain_dt_match[] = {
>> +       {
>> +               .compatible = "rockchip,rk3288-power-controller",
>> +               .data = (void *)&rk3288_pmu,
>> +       },
>> +       { /* sentinel */ },
>> +};
>> +
>> +static struct platform_driver rockchip_pm_domain_driver = {
>> +       .probe = rockchip_pm_domain_probe,
>> +       .driver = {
>> +               .name   = "rockchip-pm-domain",
>> +               .of_match_table = rockchip_pm_domain_dt_match,
>> +               /*
>> +                * We can't forcibly eject devices form power domain,
>> +                * so we can't really remove power domains once they
>> +                * were added.
>> +                */
>> +               .suppress_bind_attrs = true,
>> +       },
>> +};
>> +
>> +static int __init rockchip_pm_domain_drv_register(void)
>> +{
>> +       return platform_driver_register(&rockchip_pm_domain_driver);
>> +}
>> +postcore_initcall(rockchip_pm_domain_drv_register);
>> --
>> 1.9.1
>>
> Kind regards
> Uffe
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip




From wxt at rock-chips.com  Sat Jun 13 22:13:35 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 14 Jun 2015 13:13:35 +0800
Subject: [PATCH v15 0/4] ARM: rk3288: Add PM Domain support
Message-ID: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>

Add power domain drivers based on generic power domain for
Rockchip platform, and support RK3288.

Verified on url =
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/v3.14

The following is the easy example.

vopb: vop at ff930000 {
    compatible = "rockchip,rk3288-vop";
    ...
    iommus = <&vopb_mmu>;
    power-domains = <&power RK3288_PD_VIO>;
    status = "disabled";
    ...
};

vopb_mmu: iommu at ff930300 {
    compatible = "rockchip,iommu";
    ...
    interrupt-names = "vopb_mmu";
    power-domains = <&power RK3288_PD_VIO>;
    #iommu-cells = <0>;
    status = "disabled";
    ...
};

vopl: vop at ff940000 {
    compatible = "rockchip,rk3288-vop";
    reg = <0xff940000 0x19c>;
    ...
    iommus = <&vopl_mmu>;
    power-domains = <&power RK3288_PD_VIO>;
    status = "disabled";
    ...
};

vopl_mmu: iommu at ff940300 {
    compatible = "rockchip,iommu";
    ...
    interrupt-names = "vopl_mmu";
    power-domains = <&power RK3288_PD_VIO>;
    #iommu-cells = <0>;
    status = "disabled";
};

There is a recent addition from Linus Walleij,
called simple-mfd [a] that is supposed to get added real early for kernel 4.2

[a]:
https://git.kernel.org/cgit/linux/kernel/git/linusw/linux-integrator.git/commit/?h=simple-mfd&id=fcf294c020ff7ee4e3b1e96159e4dc7a17ad59d1

Here is my branch:

9c402ee ARM: dts: add RK3288 power-domain node
b1469c4 power-domain: rockchip: add power domain driver
ce13318 ARM: power-domain: rockchip: add the support type for the rk3288
9824091 dt-bindings: add document of Rockchip power domain
0ff0e5b MFD/OF: document MFD devices and handle simple-mfd
2bfc60d Merge tag 'misc-for-linus-4.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
...

Note:

Sorry for long no any update.

As I known, there are somethings needed to do.
(1) about all the device clocks being listed in the power-domains itself,
Someone wish was to get the clocks by reading the clocks from the device nodes,

Perhaps, this series patchs are hard to be accepted or need to do more
can be accepted.

At the moment, I send the patch v15 to discuss the issue, This patch no
any sloved the pervious issue.


Changes in v15:
- change the comment.
- As the kevin suggestion, put the power-doamin driver into driver/soc/vendor.
- As Heiko suggestion, Patch 1: binding doc, 2: binding-header, 3: driver,
  4: dts-changes.
- return -ENXIO --> return -ENODEV.
Series-changes: 14
- does not need to set an owner,remove the "THIS_MODULE".
Series-changes: 13
- Remove essential clocks from rk3288 PD_VIO domain Some clocks are essential
  for the system health and should not be turned down. However there is no owner
  for them so if they listed as belonging to power domain we'll try toggling them
  up and down during power domain.
- Device drivers expect their devices to be powered on before their
  probing code is invoked. To achieve that we should start with
  power domains powered on (we may turn them off later once all devices enable
  runtime powermanagment and go idle).
- This change switches Rockchip power domain driver to use updated
  device_attach and device_detach API.
- set the gpu/core power domain power delay time.
- fix enumerating PM clocks for devices.
- fix use after free We can't use clk after we did clk_put(clk).
Series-changes: 12
- fix the title doamin->domain.
- updated device_attach and device_detach API,otherwise it will
  compile fail on next kernel.
Series-changes: 11
- fix pm_genpd_init(&pd->genpd, NULL, false).
Series-changes: 10
- this switches over domain infos to use masks instead of recomputing
  them each time and also gets rid of custom domain translator and
  uses standard onecell on.
Series-changes: 9
- fix v8 changes as follows:
- This reconciles the v2 and v7 code so that we power domain have lists of clocks
  they trigger on and off during power transitions and independently from power
  domains clocks. We attach clocks to devices comprising power domain and prepare
  them so they are turn on and off by runtime PM.
- add rockchip_pm_add_one_domain() to control domains.
- add pd_start/pd_stop interface to control clocks.
Series-changes: 8
- This reconciles the v2 and v7 code so that we power domain have
  lists of clocks they toggle on and off during power transitions
  and independently from power domains clocks we attach clocks to
  devices comprising power domain and prepare them so they are
  turn on and off by runtime PM.
Series-changes: 7
 - Delete unused variables
Series-changes: 6
- delete pmu_lock.
- modify dev_lock using mutex.
- pm_clk_resume(pd->dev) change to pm_clk_resume(ed->dev).
- pm_clk_suspend(pd->dev) change to pm_clk_suspend(ed->dev).
- add devm_kfree(pd->dev, de) in rockchip_pm_domain_detach_dev.
Series-changes: 5
- delete idle_lock.
- add timeout in rockchip_pmu_set_idle_request().
Series-changes: 4
- use list storage dev.
Series-changes: 3
- change use pm_clk_resume() and pm_clk_suspend().
Series-changes: 2
- remove the "pd->pd.of_node = np".
- As Tomasz remarked previously the dts should represent the hardware
  and the power-domains are part of the pmu.
Series-changes: 12
- Remove essential clocks from rk3288 PD_VIO domain, Some clocks are
  essential for the system health and should not be turned down.
  However there is no owner for them so if they listed as belonging to power
  domain we'll try toggling them up and down during power domain transition.
  As a result we either fail to suspend or resume the system.
Series-changes: 10
- fix missing the #include <dt-bindings/power-domain/rk3288.h>.
- remove the notes.
Series-changes: 9
- add decription for power-doamin node.
Series-changes: 8
- DTS go back to v2.
Series-changes: 3
- Decomposition power-controller, changed to multiple controller
  (gpu-power-controller, hevc-power-controller).
Series-changes: 2
- make pd_vio clocks all one entry per line and alphabetize.
- power: power-controller move back to pinctrl: pinctrl.

Changes in v9:
- add document decription.
Series-changes:8
- document go back to v2.
Series-changes:3
- DT structure has changed.
Series-changes:2
- move clocks to "optional".

Caesar Wang (4):
  dt-bindings: add document of Rockchip power domain
  ARM: power-domain: rockchip: add the support type on RK3288
  soc: rockchip: power-domain: add power domain driver
  ARM: dts: add RK3288 power-domain node

 .../bindings/soc/rockchip/power_domain.txt         |  48 ++
 arch/arm/boot/dts/rk3288.dtsi                      |  62 +++
 drivers/soc/Kconfig                                |   1 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/rockchip/Kconfig                       |  13 +
 drivers/soc/rockchip/Makefile                      |   4 +
 drivers/soc/rockchip/pm_domains.c                  | 506 +++++++++++++++++++++
 include/dt-bindings/power-domain/rk3288.h          |  11 +
 8 files changed, 646 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/pm_domains.c
 create mode 100644 include/dt-bindings/power-domain/rk3288.h

-- 
1.9.1



From wxt at rock-chips.com  Sat Jun 13 22:13:36 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 14 Jun 2015 13:13:36 +0800
Subject: [PATCH v15 1/4] dt-bindings: add document of Rockchip power domain
In-Reply-To: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434258820-26779-2-git-send-email-wxt@rock-chips.com>

This add the necessary binding documentation for the power domain
found on Rockchip Socs.

Signed-off-by: jinkun.hong <jinkun.hong at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v15: None
Changes in v9:
- add document decription.
Series-changes:8
- document go back to v2.
Series-changes:3
- DT structure has changed.
Series-changes:2
- move clocks to "optional".

 .../bindings/soc/rockchip/power_domain.txt         | 48 ++++++++++++++++++++++
 1 file changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/rockchip/power_domain.txt

diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
new file mode 100644
index 0000000..3e74e6d
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
@@ -0,0 +1,48 @@
+* Rockchip Power Domains
+
+Rockchip processors include support for multiple power domains which can be
+powered up/down by software based on different application scenes to save power.
+
+Required properties for power domain controller:
+- compatible: should be one of the following.
+    * rockchip,rk3288-power-controller - for rk3288 type power domain.
+- #power-domain-cells: Number of cells in a power-domain specifier.
+		       should be 1.
+- rockchip,pmu: phandle referencing a syscon providing the pmu registers
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+
+Required properties for power domain sub nodes:
+- reg: index of the power domain, should use macros in:
+    *  include/dt-bindings/power-domain/rk3288.h - for rk3288 type power domain.
+- clocks (optional): phandles to clocks which need to be enabled while power domain
+          switches state.
+
+Example:
+
+	power: power-controller {
+	       compatible = "rockchip,rk3288-power-controller";
+	       #power-domain-cells = <1>;
+	       rockchip,pmu = <&pmu>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+	       pd_gpu {
+	               reg = <RK3288_PD_GPU>;
+	               clocks = <&cru ACLK_GPU>;
+	       };
+	};
+
+Node of a device using power domains must have a power-domains property,
+containing a phandle to the power device node and an index specifying which
+power domain to use.
+The index should use macros in:
+   * include/dt-bindings/power-domain/rk3288.h - for rk3288 type power domain.
+
+Example of the node using power domain:
+
+	node {
+		/* ... */
+		power-domains = <&power RK3288_PD_GPU>;
+		/* ... */
+	};
-- 
1.9.1



From wxt at rock-chips.com  Sat Jun 13 22:13:37 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 14 Jun 2015 13:13:37 +0800
Subject: [PATCH v15 2/4] ARM: power-domain: rockchip: add the support type on
 RK3288
In-Reply-To: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434258820-26779-3-git-send-email-wxt@rock-chips.com>

At the moment, we can support these power-domain type on RK3288.
We can add more types on RK3288 in the future, that's need to do.

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v15:
- change the comment.

Changes in v9: None

 include/dt-bindings/power-domain/rk3288.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 include/dt-bindings/power-domain/rk3288.h

diff --git a/include/dt-bindings/power-domain/rk3288.h b/include/dt-bindings/power-domain/rk3288.h
new file mode 100644
index 0000000..ca68c11
--- /dev/null
+++ b/include/dt-bindings/power-domain/rk3288.h
@@ -0,0 +1,11 @@
+#ifndef __DT_BINDINGS_POWER_DOMAIN_RK3288_H__
+#define __DT_BINDINGS_POWER_DOMAIN_RK3288_H__
+
+/* RK3288 power domain index */
+#define RK3288_PD_GPU          0
+#define RK3288_PD_VIO          1
+#define RK3288_PD_VIDEO        2
+#define RK3288_PD_HEVC         3
+#define RK3288_PD_PERI         4
+
+#endif
-- 
1.9.1



From wxt at rock-chips.com  Sat Jun 13 22:13:38 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 14 Jun 2015 13:13:38 +0800
Subject: [PATCH v15 3/4] soc: rockchip: power-domain: add power domain driver
In-Reply-To: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434258820-26779-4-git-send-email-wxt@rock-chips.com>

In order to meet high performance and low power requirements, a power
management unit is designed or saving power when RK3288 in low power
mode.
The RK3288 PMU is dedicated for managing the power ot the whole chip.

Signed-off-by: jinkun.hong <jinkun.hong at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v15:
- As the kevin suggestion, put the power-doamin driver into driver/soc/vendor.
- As Heiko suggestion, Patch 1: binding doc, 2: binding-header, 3: driver,
  4: dts-changes.
- return -ENXIO --> return -ENODEV.
Series-changes: 14
- does not need to set an owner,remove the "THIS_MODULE".
Series-changes: 13
- Remove essential clocks from rk3288 PD_VIO domain Some clocks are essential
  for the system health and should not be turned down. However there is no owner
  for them so if they listed as belonging to power domain we'll try toggling them
  up and down during power domain.
- Device drivers expect their devices to be powered on before their
  probing code is invoked. To achieve that we should start with
  power domains powered on (we may turn them off later once all devices enable
  runtime powermanagment and go idle).
- This change switches Rockchip power domain driver to use updated
  device_attach and device_detach API.
- set the gpu/core power domain power delay time.
- fix enumerating PM clocks for devices.
- fix use after free We can't use clk after we did clk_put(clk).
Series-changes: 12
- fix the title doamin->domain.
- updated device_attach and device_detach API,otherwise it will
  compile fail on next kernel.
Series-changes: 11
- fix pm_genpd_init(&pd->genpd, NULL, false).
Series-changes: 10
- this switches over domain infos to use masks instead of recomputing
  them each time and also gets rid of custom domain translator and
  uses standard onecell on.
Series-changes: 9
- fix v8 changes as follows:
- This reconciles the v2 and v7 code so that we power domain have lists of clocks
  they trigger on and off during power transitions and independently from power
  domains clocks. We attach clocks to devices comprising power domain and prepare
  them so they are turn on and off by runtime PM.
- add rockchip_pm_add_one_domain() to control domains.
- add pd_start/pd_stop interface to control clocks.
Series-changes: 8
- This reconciles the v2 and v7 code so that we power domain have
  lists of clocks they toggle on and off during power transitions
  and independently from power domains clocks we attach clocks to
  devices comprising power domain and prepare them so they are
  turn on and off by runtime PM.
Series-changes: 7
 - Delete unused variables
Series-changes: 6
- delete pmu_lock.
- modify dev_lock using mutex.
- pm_clk_resume(pd->dev) change to pm_clk_resume(ed->dev).
- pm_clk_suspend(pd->dev) change to pm_clk_suspend(ed->dev).
- add devm_kfree(pd->dev, de) in rockchip_pm_domain_detach_dev.
Series-changes: 5
- delete idle_lock.
- add timeout in rockchip_pmu_set_idle_request().
Series-changes: 4
- use list storage dev.
Series-changes: 3
- change use pm_clk_resume() and pm_clk_suspend().
Series-changes: 2
- remove the "pd->pd.of_node = np".

Changes in v9: None

 drivers/soc/Kconfig               |   1 +
 drivers/soc/Makefile              |   1 +
 drivers/soc/rockchip/Kconfig      |  13 +
 drivers/soc/rockchip/Makefile     |   4 +
 drivers/soc/rockchip/pm_domains.c | 506 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 525 insertions(+)
 create mode 100644 drivers/soc/rockchip/Kconfig
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/pm_domains.c

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index d8bde82..e897c0ca 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
+source "drivers/soc/rockchip/Kconfig"
 source "drivers/soc/ti/Kconfig"
 source "drivers/soc/versatile/Kconfig"
 
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 70042b2..91f7f18 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
+obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_SOC_TI)		+= ti/
 obj-$(CONFIG_PLAT_VERSATILE)	+= versatile/
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
new file mode 100644
index 0000000..5a7af4c
--- /dev/null
+++ b/drivers/soc/rockchip/Kconfig
@@ -0,0 +1,13 @@
+#
+# Rockchip Soc drivers
+#
+config PM_GENERIC_DOMAINS
+        tristate "Rockchip generic power domain"
+        depends on PM
+        help
+          Say y here to enable power doamin support.
+          In order to meet high performance and low power requirements, a power
+          management unit is designed or saving power when RK3288 in low power
+          mode. The RK3288 PMU is dedicated for managing the power ot the whole chip.
+
+          If unsure, say N.
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000..1c0fd91
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
+#
+# Rockchip Soc drivers
+#
+obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
new file mode 100644
index 0000000..edfa4f8
--- /dev/null
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -0,0 +1,506 @@
+/*
+ * Rockchip Generic power domain support.
+ *
+ * Copyright (c) 2015 ROCKCHIP, Co. 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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_domain.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <dt-bindings/power-domain/rk3288.h>
+
+struct rockchip_domain_info {
+	int pwr_mask;
+	int status_mask;
+	int req_mask;
+	int idle_mask;
+	int ack_mask;
+};
+
+struct rockchip_pmu_info {
+	u32 pwr_offset;
+	u32 status_offset;
+	u32 req_offset;
+	u32 idle_offset;
+	u32 ack_offset;
+
+	u32 core_pwrcnt_offset;
+	u32 gpu_pwrcnt_offset;
+
+	unsigned int core_power_transition_time;
+	unsigned int gpu_power_transition_time;
+
+	int num_domains;
+	const struct rockchip_domain_info *domain_info;
+};
+
+struct rockchip_pm_domain {
+	struct generic_pm_domain genpd;
+	const struct rockchip_domain_info *info;
+	struct rockchip_pmu *pmu;
+	int num_clks;
+	struct clk *clks[];
+};
+
+struct rockchip_pmu {
+	struct device *dev;
+	struct regmap *regmap;
+	const struct rockchip_pmu_info *info;
+	struct mutex mutex; /* mutex lock for pmu */
+	struct genpd_onecell_data genpd_data;
+	struct generic_pm_domain *domains[];
+};
+
+#define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd)
+
+#define DOMAIN(pwr, status, req, idle, ack)	\
+{						\
+	.pwr_mask = BIT(pwr),			\
+	.status_mask = BIT(status),		\
+	.req_mask = BIT(req),			\
+	.idle_mask = BIT(idle),			\
+	.ack_mask = BIT(ack),			\
+}
+
+#define DOMAIN_RK3288(pwr, status, req)		\
+	DOMAIN(pwr, status, req, req, (req) + 16)
+
+static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
+{
+	struct rockchip_pmu *pmu = pd->pmu;
+	const struct rockchip_domain_info *pd_info = pd->info;
+	unsigned int val;
+
+	regmap_read(pmu->regmap, pmu->info->idle_offset, &val);
+	return (val & pd_info->idle_mask) == pd_info->idle_mask;
+}
+
+static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
+					 bool idle)
+{
+	const struct rockchip_domain_info *pd_info = pd->info;
+	struct rockchip_pmu *pmu = pd->pmu;
+	unsigned int val;
+
+	regmap_update_bits(pmu->regmap, pmu->info->req_offset,
+			   pd_info->req_mask, idle ? -1U : 0);
+
+	dsb();
+
+	do {
+		regmap_read(pmu->regmap, pmu->info->ack_offset, &val);
+	} while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0));
+
+	while (rockchip_pmu_domain_is_idle(pd) != idle)
+		cpu_relax();
+
+	return 0;
+}
+
+static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
+{
+	struct rockchip_pmu *pmu = pd->pmu;
+	unsigned int val;
+
+	regmap_read(pmu->regmap, pmu->info->status_offset, &val);
+
+	/* 1'b0: power on, 1'b1: power off */
+	return !(val & pd->info->status_mask);
+}
+
+static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
+					     bool on)
+{
+	struct rockchip_pmu *pmu = pd->pmu;
+
+	regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
+			   pd->info->pwr_mask, on ? 0 : -1U);
+
+	dsb();
+
+	while (rockchip_pmu_domain_is_on(pd) != on)
+		cpu_relax();
+}
+
+static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
+{
+	int i;
+
+	mutex_lock(&pd->pmu->mutex);
+
+	if (rockchip_pmu_domain_is_on(pd) != power_on) {
+		for (i = 0; i < pd->num_clks; i++)
+			clk_enable(pd->clks[i]);
+
+		if (!power_on) {
+			/* FIXME: add code to save AXI_QOS */
+
+			/* if powering down, idle request to NIU first */
+			rockchip_pmu_set_idle_request(pd, true);
+		}
+
+		rockchip_do_pmu_set_power_domain(pd, power_on);
+
+		if (power_on) {
+			/* if powering up, leave idle mode */
+			rockchip_pmu_set_idle_request(pd, false);
+
+			/* FIXME: add code to restore AXI_QOS */
+		}
+
+		for (i = pd->num_clks - 1; i >= 0; i--)
+			clk_disable(pd->clks[i]);
+	}
+
+	mutex_unlock(&pd->pmu->mutex);
+	return 0;
+}
+
+static int rockchip_pd_power_on(struct generic_pm_domain *domain)
+{
+	struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+	return rockchip_pd_power(pd, true);
+}
+
+static int rockchip_pd_power_off(struct generic_pm_domain *domain)
+{
+	struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
+
+	return rockchip_pd_power(pd, false);
+}
+
+static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
+				  struct device *dev)
+{
+	struct clk *clk;
+	int i;
+	int error;
+
+	dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
+
+	error = pm_clk_create(dev);
+	if (error) {
+		dev_err(dev, "pm_clk_create failed %d\n", error);
+		return error;
+	}
+
+	i = 0;
+	while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
+		dev_dbg(dev, "adding clock '%s' to list of PM clocks\n",
+			__clk_get_name(clk));
+		error = pm_clk_add_clk(dev, clk);
+		clk_put(clk);
+		if (error) {
+			dev_err(dev, "pm_clk_add_clk failed %d\n", error);
+			pm_clk_destroy(dev);
+			return error;
+		}
+	}
+
+	return 0;
+}
+
+static void rockchip_pd_detach_dev(struct generic_pm_domain *genpd,
+				   struct device *dev)
+{
+	dev_dbg(dev, "detaching from power domain '%s'\n", genpd->name);
+
+	pm_clk_destroy(dev);
+}
+
+static int rockchip_pd_start_dev(struct device *dev)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
+
+	dev_dbg(dev, "starting device in power domain '%s'\n", genpd->name);
+
+	return pm_clk_resume(dev);
+}
+
+static int rockchip_pd_stop_dev(struct device *dev)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(dev->pm_domain);
+
+	dev_dbg(dev, "stopping device in power domain '%s'\n", genpd->name);
+
+	return pm_clk_suspend(dev);
+}
+
+static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
+				      struct device_node *node)
+{
+	const struct rockchip_domain_info *pd_info;
+	struct rockchip_pm_domain *pd;
+	struct clk *clk;
+	int clk_cnt;
+	int i;
+	u32 id;
+	int error;
+
+	error = of_property_read_u32(node, "reg", &id);
+	if (error) {
+		dev_err(pmu->dev,
+			"%s: failed to retrieve domain id (reg): %d\n",
+			node->name, error);
+		return -EINVAL;
+	}
+
+	if (id >= pmu->info->num_domains) {
+		dev_err(pmu->dev, "%s: invalid domain id %d\n",
+			node->name, id);
+		return -EINVAL;
+	}
+
+	pd_info = &pmu->info->domain_info[id];
+	if (!pd_info) {
+		dev_err(pmu->dev, "%s: undefined domain id %d\n",
+			node->name, id);
+		return -EINVAL;
+	}
+
+	clk_cnt = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+	pd = devm_kzalloc(pmu->dev,
+			  sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
+			  GFP_KERNEL);
+	if (!pd)
+		return -ENOMEM;
+
+	pd->info = pd_info;
+	pd->pmu = pmu;
+
+	for (i = 0; i < clk_cnt; i++) {
+		clk = of_clk_get(node, i);
+		if (IS_ERR(clk)) {
+			error = PTR_ERR(clk);
+			dev_err(pmu->dev,
+				"%s: failed to get clk %s (index %d): %d\n",
+				node->name, __clk_get_name(clk), i, error);
+			goto err_out;
+		}
+
+		error = clk_prepare(clk);
+		if (error) {
+			dev_err(pmu->dev,
+				"%s: failed to prepare clk %s (index %d): %d\n",
+				node->name, __clk_get_name(clk), i, error);
+			clk_put(clk);
+			goto err_out;
+		}
+
+		pd->clks[pd->num_clks++] = clk;
+
+		dev_dbg(pmu->dev, "added clock '%s' to domain '%s'\n",
+			__clk_get_name(clk), node->name);
+	}
+
+	error = rockchip_pd_power(pd, true);
+	if (error) {
+		dev_err(pmu->dev,
+			"failed to power on domain '%s': %d\n",
+			node->name, error);
+		goto err_out;
+	}
+
+	pd->genpd.name = node->name;
+	pd->genpd.power_off = rockchip_pd_power_off;
+	pd->genpd.power_on = rockchip_pd_power_on;
+	pd->genpd.attach_dev = rockchip_pd_attach_dev;
+	pd->genpd.detach_dev = rockchip_pd_detach_dev;
+	pd->genpd.dev_ops.start = rockchip_pd_start_dev;
+	pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;
+	pm_genpd_init(&pd->genpd, NULL, false);
+
+	pmu->genpd_data.domains[id] = &pd->genpd;
+	return 0;
+
+err_out:
+	while (--i >= 0) {
+		clk_unprepare(pd->clks[i]);
+		clk_put(pd->clks[i]);
+	}
+	return error;
+}
+
+static void rockchip_pm_remove_one_domain(struct rockchip_pm_domain *pd)
+{
+	int i;
+
+	for (i = 0; i < pd->num_clks; i++) {
+		clk_unprepare(pd->clks[i]);
+		clk_put(pd->clks[i]);
+	}
+
+	/* devm will free our memory */
+}
+
+static void rockchip_pm_domain_cleanup(struct rockchip_pmu *pmu)
+{
+	struct generic_pm_domain *genpd;
+	struct rockchip_pm_domain *pd;
+	int i;
+
+	for (i = 0; i < pmu->genpd_data.num_domains; i++) {
+		genpd = pmu->genpd_data.domains[i];
+		if (genpd) {
+			pd = to_rockchip_pd(genpd);
+			rockchip_pm_remove_one_domain(pd);
+		}
+	}
+
+	/* devm will free our memory */
+}
+
+static void rockchip_configure_pd_cnt(struct rockchip_pmu *pmu,
+				      u32 domain_reg_offset,
+				      unsigned int count)
+{
+	/* First configure domain power down transition count ... */
+	regmap_write(pmu->regmap, domain_reg_offset, count);
+	/* ... and then power up count. */
+	regmap_write(pmu->regmap, domain_reg_offset + 4, count);
+}
+
+static int rockchip_pm_domain_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *node;
+	struct device *parent;
+	struct rockchip_pmu *pmu;
+	const struct of_device_id *match;
+	const struct rockchip_pmu_info *pmu_info;
+	int error;
+
+	if (!np) {
+		dev_err(dev, "device tree node not found\n");
+		return -ENODEV;
+	}
+
+	match = of_match_device(dev->driver->of_match_table, dev);
+	if (!match || !match->data) {
+		dev_err(dev, "missing pmu data\n");
+		return -EINVAL;
+	}
+
+	pmu_info = match->data;
+
+	pmu = devm_kzalloc(dev,
+			   sizeof(*pmu) +
+				pmu_info->num_domains * sizeof(pmu->domains[0]),
+			   GFP_KERNEL);
+	if (!pmu)
+		return -ENOMEM;
+
+	pmu->dev = &pdev->dev;
+	mutex_init(&pmu->mutex);
+
+	pmu->info = pmu_info;
+
+	pmu->genpd_data.domains = pmu->domains;
+	pmu->genpd_data.num_domains = pmu_info->num_domains;
+
+	parent = dev->parent;
+	if (!parent) {
+		dev_err(dev, "no parent for syscon devices\n");
+		return -ENODEV;
+	}
+
+	pmu->regmap = syscon_node_to_regmap(parent->of_node);
+
+	/*
+	 * Configure power up and down transition delays for core
+	 * and GPU domains.
+	 */
+	rockchip_configure_pd_cnt(pmu, pmu_info->core_pwrcnt_offset,
+				  pmu_info->core_power_transition_time);
+	rockchip_configure_pd_cnt(pmu, pmu_info->gpu_pwrcnt_offset,
+				  pmu_info->gpu_power_transition_time);
+
+	error = -ENODEV;
+
+	for_each_available_child_of_node(np, node) {
+		error = rockchip_pm_add_one_domain(pmu, node);
+		if (error) {
+			dev_err(dev, "failed to handle node %s: %d\n",
+				node->name, error);
+			goto err_out;
+		}
+	}
+
+	if (error) {
+		dev_dbg(dev, "no power domains defined\n");
+		goto err_out;
+	}
+
+	of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+
+	return 0;
+
+err_out:
+	rockchip_pm_domain_cleanup(pmu);
+	return error;
+}
+
+static const struct rockchip_domain_info rk3288_pm_domains[] = {
+	[RK3288_PD_GPU]		= DOMAIN_RK3288(9, 9, 2),
+	[RK3288_PD_VIO]		= DOMAIN_RK3288(7, 7, 4),
+	[RK3288_PD_VIDEO]	= DOMAIN_RK3288(8, 8, 3),
+	[RK3288_PD_HEVC]	= DOMAIN_RK3288(14, 10, 9),
+};
+
+static const struct rockchip_pmu_info rk3288_pmu = {
+	.pwr_offset = 0x08,
+	.status_offset = 0x0c,
+	.req_offset = 0x10,
+	.idle_offset = 0x14,
+	.ack_offset = 0x14,
+
+	.core_pwrcnt_offset = 0x34,
+	.gpu_pwrcnt_offset = 0x3c,
+
+	.core_power_transition_time = 24, /* 1us */
+	.gpu_power_transition_time = 24, /* 1us */
+
+	.num_domains = ARRAY_SIZE(rk3288_pm_domains),
+	.domain_info = rk3288_pm_domains,
+};
+
+static const struct of_device_id rockchip_pm_domain_dt_match[] = {
+	{
+		.compatible = "rockchip,rk3288-power-controller",
+		.data = (void *)&rk3288_pmu,
+	},
+	{ /* sentinel */ },
+};
+
+static struct platform_driver rockchip_pm_domain_driver = {
+	.probe = rockchip_pm_domain_probe,
+	.driver = {
+		.name   = "rockchip-pm-domain",
+		.of_match_table = rockchip_pm_domain_dt_match,
+		/*
+		 * We can't forcibly eject devices form power domain,
+		 * so we can't really remove power domains once they
+		 * were added.
+		 */
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init rockchip_pm_domain_drv_register(void)
+{
+	return platform_driver_register(&rockchip_pm_domain_driver);
+}
+postcore_initcall(rockchip_pm_domain_drv_register);
-- 
1.9.1



From wxt at rock-chips.com  Sat Jun 13 22:13:39 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Sun, 14 Jun 2015 13:13:39 +0800
Subject: [PATCH v15 4/4] ARM: dts: add RK3288 power-domain node
In-Reply-To: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434258820-26779-5-git-send-email-wxt@rock-chips.com>

This patch add the needed clocks into power-controller.

There are several reasons as follows:

Firstly, the clocks need be turned off to save power when
the system enter the suspend state. So we need to enumerate the clocks
in the dts. In order to power domain can turn on and off.

Secondly, the reset-circuit should reset be synchronous on rk3288,
then sync revoked. So we need to enable clocks of all devices.

Signed-off-by: jinkun.hong <jinkun.hong at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v15:
- As Tomasz remarked previously the dts should represent the hardware
  and the power-domains are part of the pmu.
Series-changes: 12
- Remove essential clocks from rk3288 PD_VIO domain, Some clocks are
  essential for the system health and should not be turned down.
  However there is no owner for them so if they listed as belonging to power
  domain we'll try toggling them up and down during power domain transition.
  As a result we either fail to suspend or resume the system.
Series-changes: 10
- fix missing the #include <dt-bindings/power-domain/rk3288.h>.
- remove the notes.
Series-changes: 9
- add decription for power-doamin node.
Series-changes: 8
- DTS go back to v2.
Series-changes: 3
- Decomposition power-controller, changed to multiple controller
  (gpu-power-controller, hevc-power-controller).
Series-changes: 2
- make pd_vio clocks all one entry per line and alphabetize.
- power: power-controller move back to pinctrl: pinctrl.

Changes in v9: None

 arch/arm/boot/dts/rk3288.dtsi | 62 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 165968d..8224070 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -550,6 +550,68 @@
 	pmu: power-management at ff730000 {
 		compatible = "rockchip,rk3288-pmu", "syscon";
 		reg = <0xff730000 0x100>;
+
+		pmu: power-management at ff730000 {
+		compatible = "rockchip,rk3288-pmu", "syscon", "simple-mfd";
+		reg = <0xff730000 0x100>;
+
+		power: power-controller {
+			compatible = "rockchip,rk3288-power-controller";
+			#power-domain-cells = <1>;
+			rockchip,pmu = <&pmu>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			pd_gpu {
+				reg = <RK3288_PD_GPU>;
+				clocks = <&cru ACLK_GPU>;
+			};
+
+			pd_hevc {
+				reg = <RK3288_PD_HEVC>;
+				clocks = <&cru ACLK_HEVC>,
+					 <&cru SCLK_HEVC_CABAC>,
+					 <&cru SCLK_HEVC_CORE>,
+					 <&cru HCLK_HEVC>;
+			};
+
+			pd_vio {
+				reg = <RK3288_PD_VIO>;
+				clocks = <&cru ACLK_IEP>,
+					 <&cru ACLK_ISP>,
+					 <&cru ACLK_RGA>,
+					 <&cru ACLK_VIP>,
+					 <&cru ACLK_VOP0>,
+					 <&cru ACLK_VOP1>,
+					 <&cru DCLK_VOP0>,
+					 <&cru DCLK_VOP1>,
+					 <&cru HCLK_IEP>,
+					 <&cru HCLK_ISP>,
+					 <&cru HCLK_RGA>,
+					 <&cru HCLK_VIP>,
+					 <&cru HCLK_VOP0>,
+					 <&cru HCLK_VOP1>,
+					 <&cru PCLK_EDP_CTRL>,
+					 <&cru PCLK_HDMI_CTRL>,
+					 <&cru PCLK_LVDS_PHY>,
+					 <&cru PCLK_MIPI_CSI>,
+					 <&cru PCLK_MIPI_DSI0>,
+					 <&cru PCLK_MIPI_DSI1>,
+					 <&cru SCLK_EDP_24M>,
+					 <&cru SCLK_EDP>,
+					 <&cru SCLK_HDMI_CEC>,
+					 <&cru SCLK_HDMI_HDCP>,
+					 <&cru SCLK_ISP_JPE>,
+					 <&cru SCLK_ISP>,
+					 <&cru SCLK_RGA>;
+			};
+
+			pd_video {
+				reg = <RK3288_PD_VIDEO>;
+				clocks = <&cru ACLK_VCODEC>,
+					 <&cru HCLK_VCODEC>;
+			};
+		};
 	};
 
 	sgrf: syscon at ff740000 {
-- 
1.9.1



From pebolle at tiscali.nl  Mon Jun 15 08:00:19 2015
From: pebolle at tiscali.nl (Paul Bolle)
Date: Mon, 15 Jun 2015 17:00:19 +0200
Subject: [PATCH v15 3/4] soc: rockchip: power-domain: add power domain
 driver
In-Reply-To: <1434258820-26779-4-git-send-email-wxt@rock-chips.com>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>
 <1434258820-26779-4-git-send-email-wxt@rock-chips.com>
Message-ID: <1434380419.2069.38.camel@x220>

On Sun, 2015-06-14 at 13:13 +0800, Caesar Wang wrote:

> --- /dev/null
> +++ b/drivers/soc/rockchip/Kconfig

> +config PM_GENERIC_DOMAINS
> +        tristate "Rockchip generic power domain"

Since my remarks on v13 you removed the module specific code from 
pm_domains.c. But now this became a tristate symbol. That makes little
sense. Why didn't you keep bool?

> +        depends on PM
> +        help
> +          Say y here to enable power doamin support.

s/doamin/domain/.

> +          In order to meet high performance and low power requirements, a power
> +          management unit is designed or saving power when RK3288 in low power
> +          mode. The RK3288 PMU is dedicated for managing the power ot the whole chip.

s/ot/of/

> +          If unsure, say N.

Thanks,


Paul Bolle



From romain.perier at gmail.com  Mon Jun 15 10:41:41 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Mon, 15 Jun 2015 17:41:41 +0000
Subject: [PATCH] ARM: dts: rockchip: Add ramp delay for vdd_cpu in firefly
 board dts
Message-ID: <1434390101-27000-1-git-send-email-romain.perier@gmail.com>

Adds ramp delay for the vdd_cpu output. It removes warning "ramp_delay not set"
emitted by the function regulator_set_voltage_time_sel() by the same time,
which floods kernel logs.

Signed-off-by: Romain Perier <romain.perier at gmail.com>
---
 arch/arm/boot/dts/rk3288-firefly.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288-firefly.dtsi b/arch/arm/boot/dts/rk3288-firefly.dtsi
index 0b42372..0c66e92 100644
--- a/arch/arm/boot/dts/rk3288-firefly.dtsi
+++ b/arch/arm/boot/dts/rk3288-firefly.dtsi
@@ -213,6 +213,8 @@
 		regulator-max-microvolt = <1350000>;
 		regulator-always-on;
 		regulator-boot-on;
+		regulator-enable-ramp-delay = <300>;
+		regulator-ramp-delay = <8000>;
 		vin-supply = <&vcc_sys>;
 	};
 
-- 
1.9.1



From romain.perier at gmail.com  Mon Jun 15 10:44:19 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Mon, 15 Jun 2015 17:44:19 +0000
Subject: [PATCH] net: stmmac: dwmac-rk: Don't add function name in info or err
 messages
Message-ID: <1434390259-27145-1-git-send-email-romain.perier@gmail.com>

These kind of informations are only useful for debugging and should not be
displayed in normal modules message.

Signed-off-by: Romain Perier <romain.perier at gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 75 +++++++++++++-------------
 1 file changed, 36 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 30e28f0..26c339d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -98,7 +98,7 @@ static void set_to_rgmii(struct rk_priv_data *bsp_priv,
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		dev_err(dev, "Missing rockchip,grf property\n");
 		return;
 	}
 
@@ -115,7 +115,7 @@ static void set_to_rmii(struct rk_priv_data *bsp_priv)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		dev_err(dev, "Missing rockchip,grf property\n");
 		return;
 	}
 
@@ -128,7 +128,7 @@ static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		dev_err(dev, "Missing rockchip,grf property\n");
 		return;
 	}
 
@@ -147,7 +147,7 @@ static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (IS_ERR(bsp_priv->grf)) {
-		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		dev_err(dev, "Missing rockchip,grf property\n");
 		return;
 	}
 
@@ -170,46 +170,46 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 
 	bsp_priv->mac_clk_rx = devm_clk_get(dev, "mac_clk_rx");
 	if (IS_ERR(bsp_priv->mac_clk_rx))
-		dev_err(dev, "%s: cannot get clock %s\n",
-			__func__, "mac_clk_rx");
+		dev_err(dev, "cannot get clock %s\n",
+			"mac_clk_rx");
 
 	bsp_priv->mac_clk_tx = devm_clk_get(dev, "mac_clk_tx");
 	if (IS_ERR(bsp_priv->mac_clk_tx))
-		dev_err(dev, "%s: cannot get clock %s\n",
-			__func__, "mac_clk_tx");
+		dev_err(dev, "cannot get clock %s\n",
+			"mac_clk_tx");
 
 	bsp_priv->aclk_mac = devm_clk_get(dev, "aclk_mac");
 	if (IS_ERR(bsp_priv->aclk_mac))
-		dev_err(dev, "%s: cannot get clock %s\n",
-			__func__, "aclk_mac");
+		dev_err(dev, "cannot get clock %s\n",
+			"aclk_mac");
 
 	bsp_priv->pclk_mac = devm_clk_get(dev, "pclk_mac");
 	if (IS_ERR(bsp_priv->pclk_mac))
-		dev_err(dev, "%s: cannot get clock %s\n",
-			__func__, "pclk_mac");
+		dev_err(dev, "cannot get clock %s\n",
+			"pclk_mac");
 
 	bsp_priv->clk_mac = devm_clk_get(dev, "stmmaceth");
 	if (IS_ERR(bsp_priv->clk_mac))
-		dev_err(dev, "%s: cannot get clock %s\n",
-			__func__, "stmmaceth");
+		dev_err(dev, "cannot get clock %s\n",
+			"stmmaceth");
 
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
 		bsp_priv->clk_mac_ref = devm_clk_get(dev, "clk_mac_ref");
 		if (IS_ERR(bsp_priv->clk_mac_ref))
-			dev_err(dev, "%s: cannot get clock %s\n",
-				__func__, "clk_mac_ref");
+			dev_err(dev, "cannot get clock %s\n",
+				"clk_mac_ref");
 
 		if (!bsp_priv->clock_input) {
 			bsp_priv->clk_mac_refout =
 				devm_clk_get(dev, "clk_mac_refout");
 			if (IS_ERR(bsp_priv->clk_mac_refout))
-				dev_err(dev, "%s: cannot get clock %s\n",
-					__func__, "clk_mac_refout");
+				dev_err(dev, "cannot get clock %s\n",
+					"clk_mac_refout");
 		}
 	}
 
 	if (bsp_priv->clock_input) {
-		dev_info(dev, "%s: clock input from PHY\n", __func__);
+		dev_info(dev, "clock input from PHY\n");
 	} else {
 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
 			clk_set_rate(bsp_priv->clk_mac_pll, 50000000);
@@ -296,20 +296,18 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (!ldo) {
-		dev_err(dev, "%s: no regulator found\n", __func__);
+		dev_err(dev, "no regulator found\n");
 		return -1;
 	}
 
 	if (enable) {
 		ret = regulator_enable(ldo);
 		if (ret)
-			dev_err(dev, "%s: fail to enable phy-supply\n",
-				__func__);
+			dev_err(dev, "fail to enable phy-supply\n");
 	} else {
 		ret = regulator_disable(ldo);
 		if (ret)
-			dev_err(dev, "%s: fail to disable phy-supply\n",
-				__func__);
+			dev_err(dev, "fail to disable phy-supply\n");
 	}
 
 	return 0;
@@ -341,12 +339,11 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 
 	ret = of_property_read_string(dev->of_node, "clock_in_out", &strings);
 	if (ret) {
-		dev_err(dev, "%s: Can not read property: clock_in_out.\n",
-			__func__);
+		dev_err(dev, "Can not read property: clock_in_out.\n");
 		bsp_priv->clock_input = true;
 	} else {
-		dev_info(dev, "%s: clock input or output? (%s).\n",
-			 __func__, strings);
+		dev_info(dev, "clock input or output? (%s).\n",
+			 strings);
 		if (!strcmp(strings, "input"))
 			bsp_priv->clock_input = true;
 		else
@@ -356,22 +353,22 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 	ret = of_property_read_u32(dev->of_node, "tx_delay", &value);
 	if (ret) {
 		bsp_priv->tx_delay = 0x30;
-		dev_err(dev, "%s: Can not read property: tx_delay.", __func__);
-		dev_err(dev, "%s: set tx_delay to 0x%x\n",
-			__func__, bsp_priv->tx_delay);
+		dev_err(dev, "Can not read property: tx_delay.");
+		dev_err(dev, "set tx_delay to 0x%x\n",
+			bsp_priv->tx_delay);
 	} else {
-		dev_info(dev, "%s: TX delay(0x%x).\n", __func__, value);
+		dev_info(dev, "TX delay(0x%x).\n", value);
 		bsp_priv->tx_delay = value;
 	}
 
 	ret = of_property_read_u32(dev->of_node, "rx_delay", &value);
 	if (ret) {
 		bsp_priv->rx_delay = 0x10;
-		dev_err(dev, "%s: Can not read property: rx_delay.", __func__);
-		dev_err(dev, "%s: set rx_delay to 0x%x\n",
-			__func__, bsp_priv->rx_delay);
+		dev_err(dev, "Can not read property: rx_delay.");
+		dev_err(dev, "set rx_delay to 0x%x\n",
+			bsp_priv->rx_delay);
 	} else {
-		dev_info(dev, "%s: RX delay(0x%x).\n", __func__, value);
+		dev_info(dev, "RX delay(0x%x).\n", value);
 		bsp_priv->rx_delay = value;
 	}
 
@@ -381,13 +378,13 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 
 	/*rmii or rgmii*/
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
-		dev_info(dev, "%s: init for RGMII\n", __func__);
+		dev_info(dev, "init for RGMII\n");
 		set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay);
 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
-		dev_info(dev, "%s: init for RMII\n", __func__);
+		dev_info(dev, "init for RMII\n");
 		set_to_rmii(bsp_priv);
 	} else {
-		dev_err(dev, "%s: NO interface defined!\n", __func__);
+		dev_err(dev, "NO interface defined!\n");
 	}
 
 	gmac_clk_init(bsp_priv);
-- 
1.9.1



From romain.perier at gmail.com  Mon Jun 15 10:47:48 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Mon, 15 Jun 2015 17:47:48 +0000
Subject: [PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for uart2
Message-ID: <1434390468-27296-1-git-send-email-romain.perier@gmail.com>

This removes warning "ttyS2 - Failed to request dma" from kernel logs

Signed-off-by: Romain Perier <romain.perier at gmail.com>
---
 arch/arm/boot/dts/rk3288.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 22316d0..816f40a 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -385,6 +385,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart2_xfer>;
+		dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
-- 
1.9.1



From wxt at rock-chips.com  Mon Jun 15 19:00:30 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 10:00:30 +0800
Subject: [PATCH v15 3/4] soc: rockchip: power-domain: add power domain
 driver
In-Reply-To: <1434380419.2069.38.camel@x220>
References: <1434258820-26779-1-git-send-email-wxt@rock-chips.com>	
 <1434258820-26779-4-git-send-email-wxt@rock-chips.com>
 <1434380419.2069.38.camel@x220>
Message-ID: <557F833E.9000905@rock-chips.com>



? 2015?06?15? 23:00, Paul Bolle ??:
> On Sun, 2015-06-14 at 13:13 +0800, Caesar Wang wrote:
>
>> --- /dev/null
>> +++ b/drivers/soc/rockchip/Kconfig
>> +config PM_GENERIC_DOMAINS
>> +        tristate "Rockchip generic power domain"
> Since my remarks on v13 you removed the module specific code from
> pm_domains.c. But now this became a tristate symbol. That makes little
> sense. Why didn't you keep bool?

Yeah, you are right. :s/tristate/bool

I forget it when the driver is moving from 'arch/arm/mach-rockchip/' to 
'/driver/soc/rockchip/'.
>
>> +        depends on PM
>> +        help
>> +          Say y here to enable power doamin support.
> s/doamin/domain/.

Done.
>> +          In order to meet high performance and low power requirements, a power
>> +          management unit is designed or saving power when RK3288 in low power
>> +          mode. The RK3288 PMU is dedicated for managing the power ot the whole chip.
> s/ot/of/

Done.
>> +          If unsure, say N.
> Thanks,
>
>
> Paul Bolle

Thanks,

Caesar

>
>
>

-- 
Thanks,
- Caesar




From wxt at rock-chips.com  Tue Jun 16 00:27:42 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 15:27:42 +0800
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
Message-ID: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>

The original driver is uploaded by Jianqun.
Here is his patchs:
    https://patchwork.kernel.org/patch/5410341/
    https://patchwork.kernel.org/patch/5410351/

Jianqun, nevermind!
I check-pick it and re-upload the driver for the upstream.
e.g.:
    Tested by on minnie board.(kernel-4.1-rc8)
    cd /sys/devices/platform/ffb40000.efuse
    localhost ffb40000.efuse # cat cpu_leakage_show
    cpu_version_show
    The results:
            19
            2

Changes in v2:
- Change the document decription.
- Move the efuse driver into driver/soc/vendor.
- update the efuse driver.
- Add the dts node on RK3288.

Caesar Wang (3):
  soc/rockchip: Add efuse bindings for Rockchip SoC efuse driver
  soc/rockchip: efuse: Add Rockchip SoC efuse support
  ARM: dts: Add RK3288 efuse node

 .../bindings/fuse/rockchip,rockchip-efuse.txt      |  14 ++
 arch/arm/boot/dts/rk3288.dtsi                      |   5 +
 drivers/soc/Makefile                               |   1 +
 drivers/soc/rockchip/Makefile                      |   4 +
 drivers/soc/rockchip/efuse.c                       | 212 +++++++++++++++++++++
 5 files changed, 236 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fuse/rockchip,rockchip-efuse.txt
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/efuse.c

-- 
1.9.1



From wxt at rock-chips.com  Tue Jun 16 00:27:43 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 15:27:43 +0800
Subject: [PATCH v2 1/3] soc/rockchip: Add efuse bindings for Rockchip SoC
 efuse driver
In-Reply-To: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434439665-27781-2-git-send-email-wxt@rock-chips.com>

Add efuse bindings for RK3066, RK3188, RK3288 and RK3368.

Signed-off-by: Jianqun Xu <jay.xu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v2:
- Change the document decription.

 .../devicetree/bindings/fuse/rockchip,rockchip-efuse.txt   | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/fuse/rockchip,rockchip-efuse.txt

diff --git a/Documentation/devicetree/bindings/fuse/rockchip,rockchip-efuse.txt b/Documentation/devicetree/bindings/fuse/rockchip,rockchip-efuse.txt
new file mode 100644
index 0000000..f1f338e
--- /dev/null
+++ b/Documentation/devicetree/bindings/fuse/rockchip,rockchip-efuse.txt
@@ -0,0 +1,14 @@
+ROCKCHIP RK3066/RK3188/RK3288/RK3368 efuse block.
+
+Required properties:
+- compatible : should be: "rockchip,<name>-efuse"
+  "rockchip,rk3066-efuse": found on RK3066,RK3188,RK3288 and RK3368.
+- reg: Should contain 1 entry: the entry gives the physical address and length
+       of the fuse registers.
+
+Example:
+
+	efuse: efuse at ffb40000 {
+		compatible = "rockchip,rk3066-efuse";
+		reg = <0xffb40000 0x10000>;
+	};
-- 
1.9.1



From wxt at rock-chips.com  Tue Jun 16 00:27:44 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 15:27:44 +0800
Subject: [PATCH v2 2/3] soc/rockchip: efuse: Add Rockchip SoC efuse support
In-Reply-To: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434439665-27781-3-git-send-email-wxt@rock-chips.com>

Add driver for efuse found on Rockchip RK3066,RK3188,RK3288 and
RK3368 SoCs.

eFuse is organized as 32bits by 8 one-time programmable
electrical fuses with random access interface.

Signed-off-by: Jianqun Xu <jay.xu at rock-chips.com>
Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v2:
- Move the efuse driver into driver/soc/vendor.
- update the efuse driver.

 drivers/soc/Makefile          |   1 +
 drivers/soc/rockchip/Makefile |   4 +
 drivers/soc/rockchip/efuse.c  | 212 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 217 insertions(+)
 create mode 100644 drivers/soc/rockchip/Makefile
 create mode 100644 drivers/soc/rockchip/efuse.c

diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 70042b2..91f7f18 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_ARCH_MEDIATEK)	+= mediatek/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
+obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
 obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_SOC_TI)		+= ti/
 obj-$(CONFIG_PLAT_VERSATILE)	+= versatile/
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
new file mode 100644
index 0000000..4f5f9bd
--- /dev/null
+++ b/drivers/soc/rockchip/Makefile
@@ -0,0 +1,4 @@
+#
+# Rockchip Soc drivers
+#
+obj-$(CONFIG_ARCH_ROCKCHIP) += efuse.o
diff --git a/drivers/soc/rockchip/efuse.c b/drivers/soc/rockchip/efuse.c
new file mode 100644
index 0000000..1125320
--- /dev/null
+++ b/drivers/soc/rockchip/efuse.c
@@ -0,0 +1,212 @@
+/*
+ * Rockchip eFuse Driver
+ *
+ * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
+ * Author: Jianqun Xu <jay.xu at rock-chips.com>
+ * Author: Caesar Wang <wxt at rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License 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/io.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#define EFUSE_A_SHIFT			6
+#define EFUSE_A_MASK			0x3ff
+#define EFUSE_PGENB			BIT(3)
+#define EFUSE_LOAD			BIT(2)
+#define EFUSE_STROBE			BIT(1)
+#define EFUSE_CSB			BIT(0)
+
+#define REG_EFUSE_CTRL			0x0000
+#define REG_EFUSE_DOUT			0x0004
+
+#define EFUSE_BUF_SIZE			32
+#define EFUSE_CHIP_VERSION_OFFSET	6
+#define EFUSE_CHIP_VERSION_MASK		0xf
+#define EFUSE_BUF_LKG_CPU		23
+
+struct rockchip_efuse_info {
+	struct device *dev;
+	void __iomem *regs;
+	u32 buf[EFUSE_BUF_SIZE];
+};
+
+static void efuse_writel(struct rockchip_efuse_info *efuse,
+			 unsigned int value,
+			 unsigned int offset)
+{
+	writel_relaxed(value, efuse->regs + offset);
+}
+
+static unsigned int efuse_readl(struct rockchip_efuse_info *efuse,
+				unsigned int offset)
+{
+	return readl_relaxed(efuse->regs + offset);
+}
+
+int rockchip_efuse_get_cpuleakage(struct platform_device *pdev,
+				  unsigned int *value)
+{
+	struct rockchip_efuse_info *efuse;
+
+	efuse = platform_get_drvdata(pdev);
+	if (!efuse)
+		return -EAGAIN;
+
+	*value = efuse->buf[EFUSE_BUF_LKG_CPU];
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_efuse_get_cpuleakage);
+
+int rockchip_efuse_get_chip_version(struct platform_device *pdev,
+				    unsigned int *value)
+{
+	struct rockchip_efuse_info *efuse;
+
+	efuse = platform_get_drvdata(pdev);
+	if (!efuse)
+		return -EAGAIN;
+
+	*value = efuse->buf[EFUSE_CHIP_VERSION_OFFSET] &
+			EFUSE_CHIP_VERSION_MASK;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rockchip_efuse_get_chip_version);
+
+static ssize_t cpu_leakage_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int leakage;
+	int ret;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	ret = rockchip_efuse_get_cpuleakage(pdev, &leakage);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%d\n", leakage);
+}
+
+static ssize_t cpu_version_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int version;
+	int ret;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	ret = rockchip_efuse_get_chip_version(pdev, &version);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "%d\n", version);
+}
+
+static void rockchip_efuse_init(struct rockchip_efuse_info *efuse)
+{
+	unsigned int start;
+
+	efuse_writel(efuse, EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
+	udelay(1);
+
+	for (start = 0; start <= EFUSE_BUF_SIZE; start++) {
+		efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) &
+			     (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
+			     REG_EFUSE_CTRL);
+		efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) |
+			     ((start & EFUSE_A_MASK) << EFUSE_A_SHIFT),
+			     REG_EFUSE_CTRL);
+		udelay(1);
+		efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) |
+			     EFUSE_STROBE, REG_EFUSE_CTRL);
+		udelay(1);
+
+		efuse->buf[start] = efuse_readl(efuse, REG_EFUSE_DOUT);
+
+		efuse_writel(efuse, efuse_readl(efuse, REG_EFUSE_CTRL) &
+			     (~EFUSE_STROBE), REG_EFUSE_CTRL);
+		udelay(1);
+	}
+
+	/* Switch to standby mode */
+	efuse_writel(efuse, EFUSE_PGENB | EFUSE_CSB, REG_EFUSE_CTRL);
+}
+
+static DEVICE_ATTR(cpu_leakage_show, 0444, cpu_leakage_show, NULL);
+static DEVICE_ATTR(cpu_version_show, 0444, cpu_version_show, NULL);
+
+static struct attribute *efuse_attributes[] = {
+	&dev_attr_cpu_leakage_show.attr,
+	&dev_attr_cpu_version_show.attr,
+	NULL,
+};
+
+static const struct attribute_group efuse_attr_group = {
+	.attrs = efuse_attributes,
+};
+
+static int rockchip_efuse_probe(struct platform_device *pdev)
+{
+	struct rockchip_efuse_info *efuse;
+	struct resource *mem;
+	int ret;
+
+	efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_info),
+			     GFP_KERNEL);
+	if (!efuse)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	efuse->regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(efuse->regs))
+		return PTR_ERR(efuse->regs);
+
+	efuse->dev = &pdev->dev;
+
+	rockchip_efuse_init(efuse);
+
+	/*
+	 * We set driver data only after fully initializing efuse
+	 * to make sure rockchip_efuse_get_cpuleakage() and
+	 * rockchip_efuse_get_cpu_version do not return garbage.
+	 */
+	platform_set_drvdata(pdev, efuse);
+
+	ret = sysfs_create_group(&efuse->dev->kobj, &efuse_attr_group);
+	if (ret) {
+		dev_err(efuse->dev,
+			"failed to register sysfs. err: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id rockchip_efuse_match[] = {
+	{ .compatible = "rockchip,rk3066-efuse", },
+	{ /* sentinel */},
+};
+
+static struct platform_driver rockchip_efuse_driver = {
+	.probe = rockchip_efuse_probe,
+	.driver = {
+		.name = "rockchip-efuse",
+		.of_match_table = of_match_ptr(rockchip_efuse_match),
+		.suppress_bind_attrs = true,
+	},
+};
+
+module_platform_driver(rockchip_efuse_driver);
-- 
1.9.1



From wxt at rock-chips.com  Tue Jun 16 00:27:45 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 15:27:45 +0800
Subject: [PATCH v2 3/3] ARM: dts: Add RK3288 efuse node
In-Reply-To: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
Message-ID: <1434439665-27781-4-git-send-email-wxt@rock-chips.com>

Add the efuse node on RK3288, we can get some information
when enable the efuse driver.
e.g.: the CPU version, leakage.....

Signed-off-by: Caesar Wang <wxt at rock-chips.com>

---

Changes in v2:
- Add the dts node on RK3288.

 arch/arm/boot/dts/rk3288.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 165968d..423355e 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -691,6 +691,11 @@
 		};
 	};
 
+	efuse: efuse at ffb40000 {
+		compatible = "rockchip,rk3066-efuse";
+		reg = <0xffb40000 0x10000>;
+	};
+
 	gic: interrupt-controller at ffc01000 {
 		compatible = "arm,gic-400";
 		interrupt-controller;
-- 
1.9.1



From stefan.wahren at i2se.com  Tue Jun 16 01:52:58 2015
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Tue, 16 Jun 2015 10:52:58 +0200
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
Message-ID: <557FE3EA.4000306@i2se.com>

Hi Caesar,

[add Maxime and Srinivas]

Am 16.06.2015 um 09:27 schrieb Caesar Wang:
> The original driver is uploaded by Jianqun.
> Here is his patchs:
>     https://patchwork.kernel.org/patch/5410341/
>     https://patchwork.kernel.org/patch/5410351/
>
> Jianqun, nevermind!
> I check-pick it and re-upload the driver for the upstream.
> e.g.:
>     Tested by on minnie board.(kernel-4.1-rc8)
>     cd /sys/devices/platform/ffb40000.efuse
>     localhost ffb40000.efuse # cat cpu_leakage_show
>     cpu_version_show
>     The results:
>             19
>             2
>
> Changes in v2:
> - Change the document decription.
> - Move the efuse driver into driver/soc/vendor.
> - update the efuse driver.
> - Add the dts node on RK3288.
>
>

i want to mention that there is a upcoming new framework suitable for
efuse drivers:

https://lkml.org/lkml/2015/5/21/643

Unfortunately i don't know the current development state.

Regards
Stefan




From srinivas.kandagatla at linaro.org  Tue Jun 16 02:21:54 2015
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Tue, 16 Jun 2015 10:21:54 +0100
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <557FE3EA.4000306@i2se.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com>
Message-ID: <557FEAB2.1040101@linaro.org>

Hi Stefan,


On 16/06/15 09:52, Stefan Wahren wrote:
> Hi Caesar,
>
> [add Maxime and Srinivas]
>
> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>> The original driver is uploaded by Jianqun.
>> Here is his patchs:
>>      https://patchwork.kernel.org/patch/5410341/
>>      https://patchwork.kernel.org/patch/5410351/
>>
>> Jianqun, nevermind!
>> I check-pick it and re-upload the driver for the upstream.
>> e.g.:
>>      Tested by on minnie board.(kernel-4.1-rc8)
>>      cd /sys/devices/platform/ffb40000.efuse
>>      localhost ffb40000.efuse # cat cpu_leakage_show
>>      cpu_version_show
>>      The results:
>>              19
>>              2
>>
>> Changes in v2:
>> - Change the document decription.
>> - Move the efuse driver into driver/soc/vendor.
>> - update the efuse driver.
>> - Add the dts node on RK3288.
>>
>>
>
> i want to mention that there is a upcoming new framework suitable for
> efuse drivers:
>
> https://lkml.org/lkml/2015/5/21/643
>
> Unfortunately i don't know the current development state.
>

Currently this framework is used by atleast 3 drivers(qcom-tsens, 
qcom-cpr, begel-bone-cape manager) which are still floating in the 
mailing list.

I was hoping that these 3 users would getback with tested-by.. which did 
not happen for last 3-4 weeks.

I would appreciate, If you could try framework too, and let me know.

I added two of wrappers on top of v5 at: 
https://git.linaro.org/people/srinivas.kandagatla/linux.git/shortlog/refs/heads/nvmem-dev-v5


I think I should request Mark to take the framework.



--srini
> Regards
> Stefan
>
>


From wxt at rock-chips.com  Tue Jun 16 03:06:04 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Tue, 16 Jun 2015 18:06:04 +0800
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <557FEAB2.1040101@linaro.org>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com> <557FEAB2.1040101@linaro.org>
Message-ID: <557FF50C.10809@rock-chips.com>

Hi Srinivas,

? 2015?06?16? 17:21, Srinivas Kandagatla ??:
> Hi Stefan,
>
>
> On 16/06/15 09:52, Stefan Wahren wrote:
>> Hi Caesar,
>>
>> [add Maxime and Srinivas]
>>
>> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>>> The original driver is uploaded by Jianqun.
>>> Here is his patchs:
>>>      https://patchwork.kernel.org/patch/5410341/
>>>      https://patchwork.kernel.org/patch/5410351/
>>>
>>> Jianqun, nevermind!
>>> I check-pick it and re-upload the driver for the upstream.
>>> e.g.:
>>>      Tested by on minnie board.(kernel-4.1-rc8)
>>>      cd /sys/devices/platform/ffb40000.efuse
>>>      localhost ffb40000.efuse # cat cpu_leakage_show
>>>      cpu_version_show
>>>      The results:
>>>              19
>>>              2
>>>
>>> Changes in v2:
>>> - Change the document decription.
>>> - Move the efuse driver into driver/soc/vendor.
>>> - update the efuse driver.
>>> - Add the dts node on RK3288.
>>>
>>>
>>
>> i want to mention that there is a upcoming new framework suitable for
>> efuse drivers:
>>
>> https://lkml.org/lkml/2015/5/21/643
>>
>> Unfortunately i don't know the current development state.
>>
>
> Currently this framework is used by atleast 3 drivers(qcom-tsens, 
> qcom-cpr, begel-bone-cape manager) which are still floating in the 
> mailing list.
>
> I was hoping that these 3 users would getback with tested-by.. which 
> did not happen for last 3-4 weeks.
>
> I would appreciate, If you could try framework too, and let me know.

Okay,
I will do that...

Doing.....
203d56b WIP: nvmem: add device tree helper functions
7d822d7 nvmem: sunxi: Move the SID driver to the nvmem framework
f54130d nvmem: qfprom: Add bindings for qfprom
6e078d2 nvmem: qfprom: Add Qualcomm QFPROM support.
750d32b nvmem: Add simple nvmem-mmio consumer helper functions.
6390111 nvmem: Add bindings for simple nvmem framework
1c02217 nvmem: Add nvmem_device based consumer apis.
61ce74f nvmem: Add a simple NVMEM framework for consumers
0f82237 nvmem: Add a simple NVMEM framework for nvmem providers
7547598 regmap: Introduce regmap_get_reg_stride.
f3bc1c0 regmap: Introduce regmap_get_max_register.
f0b3b70 ARM: rockchip: fix the SMP code style
8a28ee6 ARM: rockchip: ensure CPU to enter WFI/WFE state
609deeb ARM: rockchip: fix the CPU soft reset
2a876e4 ARM: rockchip: restore dapswjdp after suspend
e260818 Linux 4.1-rc4
ab992dc watchdog: Fix merge 'conflict'
....

At the moment, I don't know how to use this framework.
I need some time to dig it, I'm happy if you some reference(driver or 
document).

>
> I added two of wrappers on top of v5 at: 
> https://git.linaro.org/people/srinivas.kandagatla/linux.git/shortlog/refs/heads/nvmem-dev-v5
>
>
> I think I should request Mark to take the framework.
>
>
>
> --srini
>> Regards
>> Stefan
>>
>>
>
>
>

-- 
Thanks,
- Caesar




From srinivas.kandagatla at linaro.org  Tue Jun 16 03:54:40 2015
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Tue, 16 Jun 2015 11:54:40 +0100
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <557FF50C.10809@rock-chips.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com> <557FEAB2.1040101@linaro.org>
 <557FF50C.10809@rock-chips.com>
Message-ID: <55800070.5030509@linaro.org>



On 16/06/15 11:06, Caesar Wang wrote:
> Hi Srinivas,
>
> ? 2015?06?16? 17:21, Srinivas Kandagatla ??:
>> Hi Stefan,
>>
>>
>> On 16/06/15 09:52, Stefan Wahren wrote:
>>> Hi Caesar,
>>>
>>> [add Maxime and Srinivas]
>>>
>>> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>>>> The original driver is uploaded by Jianqun.
>>>> Here is his patchs:
>>>>      https://patchwork.kernel.org/patch/5410341/
>>>>      https://patchwork.kernel.org/patch/5410351/
>>>>
>>>> Jianqun, nevermind!
>>>> I check-pick it and re-upload the driver for the upstream.
>>>> e.g.:
>>>>      Tested by on minnie board.(kernel-4.1-rc8)
>>>>      cd /sys/devices/platform/ffb40000.efuse
>>>>      localhost ffb40000.efuse # cat cpu_leakage_show
>>>>      cpu_version_show
>>>>      The results:
>>>>              19
>>>>              2
>>>>
>>>> Changes in v2:
>>>> - Change the document decription.
>>>> - Move the efuse driver into driver/soc/vendor.
>>>> - update the efuse driver.
>>>> - Add the dts node on RK3288.
>>>>
>>>>
>>>
>>> i want to mention that there is a upcoming new framework suitable for
>>> efuse drivers:
>>>
>>> https://lkml.org/lkml/2015/5/21/643
>>>
>>> Unfortunately i don't know the current development state.
>>>
>>
>> Currently this framework is used by atleast 3 drivers(qcom-tsens,
>> qcom-cpr, begel-bone-cape manager) which are still floating in the
>> mailing list.
>>
>> I was hoping that these 3 users would getback with tested-by.. which
>> did not happen for last 3-4 weeks.
>>
>> I would appreciate, If you could try framework too, and let me know.
>
> Okay,
> I will do that...
>
> Doing.....
> 203d56b WIP: nvmem: add device tree helper functions
> 7d822d7 nvmem: sunxi: Move the SID driver to the nvmem framework
> f54130d nvmem: qfprom: Add bindings for qfprom
> 6e078d2 nvmem: qfprom: Add Qualcomm QFPROM support.
> 750d32b nvmem: Add simple nvmem-mmio consumer helper functions.
> 6390111 nvmem: Add bindings for simple nvmem framework
> 1c02217 nvmem: Add nvmem_device based consumer apis.
> 61ce74f nvmem: Add a simple NVMEM framework for consumers
> 0f82237 nvmem: Add a simple NVMEM framework for nvmem providers
> 7547598 regmap: Introduce regmap_get_reg_stride.
> f3bc1c0 regmap: Introduce regmap_get_max_register.
> f0b3b70 ARM: rockchip: fix the SMP code style
> 8a28ee6 ARM: rockchip: ensure CPU to enter WFI/WFE state
> 609deeb ARM: rockchip: fix the CPU soft reset
> 2a876e4 ARM: rockchip: restore dapswjdp after suspend
> e260818 Linux 4.1-rc4
> ab992dc watchdog: Fix merge 'conflict'
> ....
>
> At the moment, I don't know how to use this framework.
> I need some time to dig it, I'm happy if you some reference(driver or
> document).
These are very simple apis which are listed in nvmem-consumer.h 
nvmem-provider.h. I will try to come up with some doc very soon.. thanks 
for your patience.

I just had a look at the efuse driver and all you need is(I did not do 
any compile testing) : Have a look at qfprom.c file, the drivers are 
based on regmap, so you get lot of flexibility to add custom 
reads/caches and lot of other regmap features.

dt:
/* Provider */
	efuse: efuse at ffb40000 {
		compatible = "rockchip,rk3066-efuse";
		reg = <0xffb40000 0x10000>;
		cpu_leakage: cpu_leakage {
			reg = <17 0x4>;
		};
		chip_version: chip_version {
			reg = <0x6 0x1>;
		};
	};

/* Consumer dt: */

	consumer-driver at 0 {
		nvmem-cell = <&cpu_leakage>;
		nvmem-cell-names = "cpu-leakage";

	};

/ * consumer driver */
nvmem_cell_get()/nvmem_cell_put();
nvmem_cell_read()/nvmem_cell_write();
	
/* Provider driver */ : drivers/nvmem/rockchip_efuse.c

#include <linux/module.h>
#include <linux/of.h>
#include "nvmem-mmio.h"

int rockchip_efuse_reg_read(void *context, unsigned int reg, unsigned 
int *val)
{
	/* efuse specific read sequence */
	...
}

static struct regmap_config rockchip_efuse_regmap_config = {
	.reg_bits = 32,
	.val_bits = 8,
	.reg_stride = 1,
	.reg_read = rockchip_efuse_reg_read,
};

static struct nvmem_config econfig = {
	.name = "rockchip-efuse",
	.owner = THIS_MODULE,
};

static struct nvmem_mmio_data rockchip_efuse_data = {
	.nvmem_config = &econfig,
	.regmap_config = &rockchip_efuse_regmap_config,
};

static const struct of_device_id rockchip_efuse_of_match[] = {
	{ .compatible = "rockchip,rk3066-efuse", .data = &rockchip_efuse_data},
	{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, rockchip_efuse_of_match);

static struct platform_driver rockchip_efuse_driver = {
	.probe = nvmem_mmio_probe,
	.remove = nvmem_mmio_remove,
	.driver = {
		.name = "rockchip_efuse",
		.of_match_table = rockchip_efuse_of_match,
	},
};
module_platform_driver(rockchip_efuse_driver);
MODULE_DESCRIPTION("rockchip_efuse driver");
MODULE_LICENSE("GPL v2");
>
>>
>> I added two of wrappers on top of v5 at:
>> https://git.linaro.org/people/srinivas.kandagatla/linux.git/shortlog/refs/heads/nvmem-dev-v5
>>
>>
>>
>> I think I should request Mark to take the framework.
>>
>>
>>
>> --srini
>>> Regards
>>> Stefan
>>>
>>>
>>
>>
>>
>


From heiko at sntech.de  Tue Jun 16 04:37:33 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Tue, 16 Jun 2015 13:37:33 +0200
Subject: [PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for uart2
In-Reply-To: <1434390468-27296-1-git-send-email-romain.perier@gmail.com>
References: <1434390468-27296-1-git-send-email-romain.perier@gmail.com>
Message-ID: <34159914.9nlETdacuk@phil>

Hi,

Am Montag, 15. Juni 2015, 17:47:48 schrieb Romain Perier:
> This removes warning "ttyS2 - Failed to request dma" from kernel logs
> 
> Signed-off-by: Romain Perier <romain.perier at gmail.com>
> ---
>  arch/arm/boot/dts/rk3288.dtsi | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
> index 22316d0..816f40a 100644
> --- a/arch/arm/boot/dts/rk3288.dtsi
> +++ b/arch/arm/boot/dts/rk3288.dtsi
> @@ -385,6 +385,8 @@
>  		clock-names = "baudclk", "apb_pclk";
>  		pinctrl-names = "default";
>  		pinctrl-0 = <&uart2_xfer>;
> +		dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
> +		dma-names = "tx", "rx";
>  		status = "disabled";
>  	};

The dma channels are a property of the hardware, so we probably should add 
them for all uarts in one go, instead of everytime something complains :-)

in dmac_peri
uart0: tx 1, rx 2
uart1: tx 3, rx 4
uart3: tx 7, rx 8
uart4: tx 9, rx 10


Just for the record and if anybody is interested to work in this, we have an 
issue with the dma implementation [0] that is not yet solved upstream. From 
what I've remember, that mostly got triggered on higher speeds, like higher 
spi-speeds or i2s audio stuff (poping).


Heiko

[0] 
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/93c3b192dca7e8c773c4d28873114c325382b63e%5E%21/#F0




From romain.perier at gmail.com  Tue Jun 16 10:19:26 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Tue, 16 Jun 2015 17:19:26 +0000
Subject: [PATCH] ARM: dts: rockchip: Add DMA tx and rx channels in UART
 interfaces for RK3288 SoCs
Message-ID: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>

This enable DMA capability for the corresponding UART interfaces, also it removes
warning "ttyS%d - Failed to request dma" from kernel logs.

Signed-off-by: Romain Perier <romain.perier at gmail.com>
---

Changes since v1 ("[PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for uart2"):
	- Add DMA tx and rx channels for all UART interfaces
	- Rename commit summary

 arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 22316d0..1996452 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -359,6 +359,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart0_xfer>;
+		dmas = <&dmac_peri 1>, <&dmac_peri 2>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
@@ -372,6 +374,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart1_xfer>;
+		dmas = <&dmac_peri 3>, <&dmac_peri 4>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
@@ -385,6 +389,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart2_xfer>;
+		dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
@@ -398,6 +404,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart3_xfer>;
+		dmas = <&dmac_peri 7>, <&dmac_peri 8>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
@@ -411,6 +419,8 @@
 		clock-names = "baudclk", "apb_pclk";
 		pinctrl-names = "default";
 		pinctrl-0 = <&uart4_xfer>;
+		dmas = <&dmac_peri 9>, <&dmac_peri 10>;
+		dma-names = "tx", "rx";
 		status = "disabled";
 	};
 
-- 
1.9.1



From linus.walleij at linaro.org  Wed Jun 17 01:20:32 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 17 Jun 2015 10:20:32 +0200
Subject: [PATCH 1/2] pinctrl: rockchip: generalize perpin driver-strength
 setting
In-Reply-To: <2322857.kblfsanYOB@diego>
References: <2322857.kblfsanYOB@diego>
Message-ID: <CACRpkda7U++34xSi-ePb4g7tZLde80YSaooY6WHcM=n097ZiGg@mail.gmail.com>

On Fri, Jun 12, 2015 at 11:50 PM, Heiko St?bner <heiko at sntech.de> wrote:

> The upcoming support for the RK3368 ARM64 SoC also supports perpin
> drive strength settings (at different register positions), so generalize
> the register and offset calculation to easily support this one too.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

Patch applied.

Yours,
Linus Walleij


From linus.walleij at linaro.org  Wed Jun 17 01:21:40 2015
From: linus.walleij at linaro.org (Linus Walleij)
Date: Wed, 17 Jun 2015 10:21:40 +0200
Subject: [PATCH 2/2] pinctrl: rockchip: add support for the rk3368
In-Reply-To: <6672678.KPGUcFJOAs@diego>
References: <2322857.kblfsanYOB@diego>
	<6672678.KPGUcFJOAs@diego>
Message-ID: <CACRpkdYm0XL1w_5VnaaXjnt7gR=RtO0w=Q4kVdsJNH6o+12fOA@mail.gmail.com>

On Fri, Jun 12, 2015 at 11:51 PM, Heiko St?bner <heiko at sntech.de> wrote:

> The rk3368 is the first ARM64 soc from Rockchip, but seems to share most
> peripherals with the ARM32 soc, including the pinctrl functionality.
> The only notable difference is - as with every Rockchip soc - that the
> offsets in the General Register Files moved around and a split of the pmu
> section of the rk3288 into pmu and pmugrf (pmu general register files)
> sections. The pinctrl driver of course only needs the pmugrf registers
> for controlling the pin settings.
>
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

Patch applied.

Yours,
Linus Walleij


From dianders at chromium.org  Wed Jun 17 10:01:48 2015
From: dianders at chromium.org (Doug Anderson)
Date: Wed, 17 Jun 2015 10:01:48 -0700
Subject: [PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for uart2
In-Reply-To: <34159914.9nlETdacuk@phil>
References: <1434390468-27296-1-git-send-email-romain.perier@gmail.com>
 <34159914.9nlETdacuk@phil>
Message-ID: <CAD=FV=UdrE1PCnfHiYKDm985joX4OLLYemhqm+niPUgYQO4s3Q@mail.gmail.com>

Hi,

On Tue, Jun 16, 2015 at 4:37 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> Just for the record and if anybody is interested to work in this, we have an
> issue with the dma implementation [0] that is not yet solved upstream. From
> what I've remember, that mostly got triggered on higher speeds, like higher
> spi-speeds or i2s audio stuff (poping).
>
>
> Heiko
>
> [0]
> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/93c3b192dca7e8c773c4d28873114c325382b63e%5E%21/#F0

Right.  In the ChromeOS tree (used for rk3288-based Chromebooks) we
think we solved the DMA issues for the most part by using burst mode.
...but we weren't brave enough to enable DMA for SPI and UART because
we didn't want to track down any additional weird issues and PIO mode
was working well enough.


The full list of things I see in the PL330 driver in ChromeOS:

3e12510 CHROMIUM: dmaengine: pl330: add quirk for broken no flushp
ded3780 CHROMIUM: dmaengine: pl330: support quirks for some broken
7af450f FROMLIST: DMA: pl330: support burst mode for dev-to-mem and
mem-to-dev transmit

Skimming through the i2s driver (which we definitely use with DMA):

21fee4b CHROMIUM: ASoC: rockchip_i2s: modify DMA max burst to 1
4001251 UPSTREAM: ASoC: rockchip: i2s: fix maxburst of dma data to 4

...I was only peripherally involved here, but as you can see it looks
like there were not only changes needed to the PL330 driver but also
changes needed to the DMA client.

You can find links to patches from the same git tree that Heiko pointed at.


From dinh.linux at gmail.com  Wed Jun 17 13:35:13 2015
From: dinh.linux at gmail.com (Dinh Nguyen)
Date: Wed, 17 Jun 2015 15:35:13 -0500
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
 <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
Message-ID: <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>

On Mon, Jun 1, 2015 at 6:50 AM, Geert Uytterhoeven <geert at linux-m68k.org> wrote:
> Hi Russell,
>
> On Mon, Jun 1, 2015 at 12:53 PM, Russell King - ARM Linux
> <linux at arm.linux.org.uk> wrote:
>> On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
>>> FWIW, I have the feeling this has a slight influence on boot reliability on
>>> two of my boards:
>>>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
>>>     its bootloader, seems to have a higher change of booting successfully on
>>>     cold boot,
>>>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
>>>     seems to have a lower chance of booting successfully.
>>>
>>> No time to spend all week turning this into a statistical significant test
>>> project... The reset button is my friend...
>>
>> Damn it, you sent this right after I merged and pushed out this change in
>> my for-arm-soc branch, and was just about to send it to the arm-soc people.
>> What excellent timing you have. :)
>
> Don't worry, I didn't send that email to make you postpone this change.
> Giving the fuzziness of reproduction, and the flakiness (esp. on Armadillo)
> of the boot loader, and these are old SoCs, please go ahead.
>
>> What happens on the kzm9g if you revert the mach-shmobile changes?
>
> Seems to make no difference.
>
>> For armadillo, do you use the decompressor?  That should be doing all the
>> cache cleaning already, prior to the kernel being entered.
>
> I think so.
>
> Corruption pattern ranges from lock up, over "Error: unrecognized/unsupported
> machine ID", to booting almost completely, but lacking a few devices due to
> a corrupted DTB. Been like that as long as I remember, i.e. since I got the
> board ca. 1 year ago. Boots fine (100%) with kexec.
>

It seems like this patch is causing the SoCFPGA to not boot with SMP
reliably. About 1 out of every 10 reboots, I'm seeing the boot failure
below. The error seems to only happen when I do a cold or warm reboot,
but never occurs during a power-up. If I revert this patch, or put
back the call to v7_invalidate_l1 in socfpga_secondary_startup , then
its able to boot 100% of the time.

Just wondering if anyone else is seeing something similar?

I am testing this on both linux-next and arm-soc/rmk/for-arm-soc. When
the failure happens, here's the log:

Booting Linux on physical CPU 0x0
Initializing cgroup subsys cpuset
Linux version 4.1.0-rc8-next-20150617-00002-gdd1f624
(dinguyen at linux-builds1) (gcc version 4.7.3 20130226 (prerelease)
(crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03)
) #1 SMP Wed Jun 17 14:22:59 CDT 2015
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine model: Altera SOCFPGA Cyclone V SoC Development Kit
Truncating RAM at 0x00000000-0x40000000 to -0x2f800000
Memory policy: Data cache writealloc
On node 0 totalpages: 194560
free_area_init_node: node 0, pgdat c0692640, node_mem_map ef20b000
  Normal zone: 1520 pages used for memmap
  Normal zone: 0 pages reserved
  Normal zone: 194560 pages, LIFO batch:31
PERCPU: Embedded 12 pages/cpu @ef1e1000 s19648 r8192 d21312 u49152
pcpu-alloc: s19648 r8192 d21312 u49152 alloc=12*4096
pcpu-alloc: [0] 0 [0] 1
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 193040
Kernel command line: console=ttyS0,115200 root=/dev/mmcblk0p2 rw
rootwait ip=dhcp earlyprintk
PID hash table entries: 4096 (order: 2, 16384 bytes)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 764288K/778240K available (4782K kernel code, 286K rwdata,
1344K rodata, 304K init, 135K bss, 13952K reserved, 0K cma-reserved)
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0xf0000000 - 0xff000000   ( 240 MB)
    lowmem  : 0xc0000000 - 0xef800000   ( 760 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .text : 0xc0008000 - 0xc0603e78   (6128 kB)
      .init : 0xc0604000 - 0xc0650000   ( 304 kB)
      .data : 0xc0650000 - 0xc0697920   ( 287 kB)
       .bss : 0xc0697920 - 0xc06b976c   ( 136 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
Hierarchical RCU implementation.
    Additional per-CPU info printed with stalls.
    Build-time adjustment of leaf fanout to 32.
NR_IRQS:16 nr_irqs:16 16
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 dynamic clock gating enabled, standby mode enabled
L2C-310 cache controller enabled, 8 ways, 512 kB
L2C-310: CACHE_ID 0x410030c9, AUX_CTRL 0x46060001
clocksource: timer1: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 19112604467 ns
sched_clock: 32 bits at 100MHz, resolution 10ns, wraps every 21474836475ns
Console: colour dummy device 80x30
Calibrating delay loop... 1836.64 BogoMIPS (lpj=9183232)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
CPU: Testing write buffer coherency: ok
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x8280 - 0x82d8
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
Internal error: Oops - undefined instruction: 0 [#1] SMP ARM
Modules linked in:
CPU: 1 PID: 0 Comm: swapper/1 Not tainted
4.1.0-rc8-next-20150617-00002-gdd1f624 #1
Hardware name: Altera SOCFPGA
task: eecaeac0 ti: eecce000 task.ti: eecce000
PC is at vfp_notifier+0x58/0x12c
LR is at notifier_call_chain+0x44/0x84
pc : [<c000a6bc>]    lr : [<c003d134>]    psr: 80000193
sp : eeccff48  ip : c06563c8  fp : eeccffd4
r10: eecaef80  r9 : ef1f1300  r8 : 00000002
r7 : eecd0000  r6 : c0656bc0  r5 : 00000000  r4 : eecd0000
r3 : c000a664  r2 : eecd0000  r1 : 00000002  r0 : c06563c8
Flags: Nzcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 10c5387d  Table: 0000404a  DAC: 00000015
Process swapper/1 (pid: 0, stack limit = 0xeecce218)
Stack: (0xeeccff48 to 0xeecd0000)
ff40:                   c000a664 ffffffff 00000000 c003d134 eecd0018 eecaeac0
ff60: c06648e0 0b52d2f9 c048cfa8 c003d18c 00000000 f0002100 00000001 c003d1ac
ff80: 00000000 eecaeac0 c064f300 c001369c c064b304 c0013140 00000000 ef1ed328
ffa0: eeccffe8 c001e760 c0486ec4 2eba2000 c06957c0 c06524dc 00000015 c06957c0
ffc0: c048c778 c064b304 c06957c0 00000000 eeccffdc c0486ec4 eeccffe4 c0487138
ffe0: 00000001 c00544e8 c0009494 c0697bc0 00000000 000094ac 7ef5bffd 3f39b3f8
[<c000a6bc>] (vfp_notifier) from [<c003d134>] (notifier_call_chain+0x44/0x84)
[<c003d134>] (notifier_call_chain) from [<c003d18c>]
(__atomic_notifier_call_chain+0x18/0x20)
[<c003d18c>] (__atomic_notifier_call_chain) from [<c003d1ac>]
(atomic_notifier_call_chain+0x18/0x20)
[<c003d1ac>] (atomic_notifier_call_chain) from [<c001369c>]
(__switch_to+0x34/0x58)
Code: e3a03002 e5843208 e3a00000 e8bd8038 (eef85a10)
---[ end trace 9eaea9661b3b550a ]---
Kernel panic - not syncing: Attempted to kill the idle task!
SMP: failed to stop secondary CPUs
---[ end Kernel panic - not syncing: Attempted to kill the idle task!

Dinh


From linux at arm.linux.org.uk  Wed Jun 17 14:30:07 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 17 Jun 2015 22:30:07 +0100
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
 <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
 <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>
Message-ID: <20150617213006.GC7557@n2100.arm.linux.org.uk>

On Wed, Jun 17, 2015 at 03:35:13PM -0500, Dinh Nguyen wrote:
> On Mon, Jun 1, 2015 at 6:50 AM, Geert Uytterhoeven <geert at linux-m68k.org> wrote:
> > Hi Russell,
> >
> > On Mon, Jun 1, 2015 at 12:53 PM, Russell King - ARM Linux
> > <linux at arm.linux.org.uk> wrote:
> >> On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
> >>> FWIW, I have the feeling this has a slight influence on boot reliability on
> >>> two of my boards:
> >>>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
> >>>     its bootloader, seems to have a higher change of booting successfully on
> >>>     cold boot,
> >>>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
> >>>     seems to have a lower chance of booting successfully.
> >>>
> >>> No time to spend all week turning this into a statistical significant test
> >>> project... The reset button is my friend...
> >>
> >> Damn it, you sent this right after I merged and pushed out this change in
> >> my for-arm-soc branch, and was just about to send it to the arm-soc people.
> >> What excellent timing you have. :)
> >
> > Don't worry, I didn't send that email to make you postpone this change.
> > Giving the fuzziness of reproduction, and the flakiness (esp. on Armadillo)
> > of the boot loader, and these are old SoCs, please go ahead.
> >
> >> What happens on the kzm9g if you revert the mach-shmobile changes?
> >
> > Seems to make no difference.
> >
> >> For armadillo, do you use the decompressor?  That should be doing all the
> >> cache cleaning already, prior to the kernel being entered.
> >
> > I think so.
> >
> > Corruption pattern ranges from lock up, over "Error: unrecognized/unsupported
> > machine ID", to booting almost completely, but lacking a few devices due to
> > a corrupted DTB. Been like that as long as I remember, i.e. since I got the
> > board ca. 1 year ago. Boots fine (100%) with kexec.
> >
> 
> It seems like this patch is causing the SoCFPGA to not boot with SMP
> reliably. About 1 out of every 10 reboots, I'm seeing the boot failure
> below. The error seems to only happen when I do a cold or warm reboot,
> but never occurs during a power-up. If I revert this patch, or put
> back the call to v7_invalidate_l1 in socfpga_secondary_startup , then
> its able to boot 100% of the time.

It really sucks that you're only just testing this change now, because
I've frozen my tree, and removing it for the next merge window is going
to be an entirely non-trivial matter.  You were copied on the original
patch, which you failed to test... I can't say I have _much_ sympathy
for a bug report at this point in time.

> Internal error: Oops - undefined instruction: 0 [#1] SMP ARM
> Modules linked in:
> CPU: 1 PID: 0 Comm: swapper/1 Not tainted
> 4.1.0-rc8-next-20150617-00002-gdd1f624 #1
> Hardware name: Altera SOCFPGA
> task: eecaeac0 ti: eecce000 task.ti: eecce000
> PC is at vfp_notifier+0x58/0x12c
> LR is at notifier_call_chain+0x44/0x84

This suggests that access to the VFP coprocessor is still disabled.
However, vfp_hotplug() should have been called for CPU1 before it
gets here, which should call vfp_enable(), which should enable access.

However, what I'm wondering is...

> [<c000a6bc>] (vfp_notifier) from [<c003d134>] (notifier_call_chain+0x44/0x84)
> [<c003d134>] (notifier_call_chain) from [<c003d18c>]
> (__atomic_notifier_call_chain+0x18/0x20)
> [<c003d18c>] (__atomic_notifier_call_chain) from [<c003d1ac>]
> (atomic_notifier_call_chain+0x18/0x20)
> [<c003d1ac>] (atomic_notifier_call_chain) from [<c001369c>]
> (__switch_to+0x34/0x58)

what the rest of the trace is.  Unfortunately, we mark __switch_to() as
"cantunwind" which means the unwinder always stops here.  It would be
really good to know what is responsible for this scheduling event,
whether it's due to a lock which is tried to be taken but is found to
be locked, but I don't think we can modify __switch_to() to allow it
to unwind (and I don't have the unwinder knowledge to hand to hack
something together.)

In order to see what's going on here, we do need to see the rest of the
trace... right now I don't have the time to be able to sort out
__switch_to() to achieve that.

As I say, you should have tested this earlier.  About the only thing I
can do now is to revert the entire original patch, which is going to be
extremely disruptive as it'll cause yet more conflicts between trees -
again, something that we want to be avoiding at this stage in the game.

Please test patches earlier.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From heiko at sntech.de  Wed Jun 17 14:54:43 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 17 Jun 2015 23:54:43 +0200
Subject: [PATCH 1/4] net: stmmac: dwmac-rk: remove unused gpio register defines
In-Reply-To: <1434578086-12209-1-git-send-email-heiko@sntech.de>
References: <1434578086-12209-1-git-send-email-heiko@sntech.de>
Message-ID: <1434578086-12209-2-git-send-email-heiko@sntech.de>

In a first version the driver did want to do some gpio wiggling, which
of course never made it into the kernel, but somehow these register
defines where forgotten. Remove them, as they shouldn't be here.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 30e28f0..49c7715 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -65,9 +65,6 @@ struct rk_priv_data {
 
 #define RK3288_GRF_SOC_CON1	0x0248
 #define RK3288_GRF_SOC_CON3	0x0250
-#define RK3288_GRF_GPIO3D_E	0x01ec
-#define RK3288_GRF_GPIO4A_E	0x01f0
-#define RK3288_GRF_GPIO4B_E	0x01f4
 
 /*RK3288_GRF_SOC_CON1*/
 #define GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
-- 
2.1.4



From heiko at sntech.de  Wed Jun 17 14:54:45 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 17 Jun 2015 23:54:45 +0200
Subject: [PATCH 3/4] net: stmmac: dwmac-rk: abstract access to mac settings in
 GRF
In-Reply-To: <1434578086-12209-1-git-send-email-heiko@sntech.de>
References: <1434578086-12209-1-git-send-email-heiko@sntech.de>
Message-ID: <1434578086-12209-4-git-send-email-heiko@sntech.de>

The mac settings like RGMII/RMII, speeds etc are done in the so called
"General Register Files", contain numerous other settings as well and
always seem to change between Rockchip SoCs. Therefore abstract the
register accesses into a per-soc ops struct to make this reusable on
other Rockchip SoCs.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 116 ++++++++++++++++---------
 1 file changed, 75 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 4faa283..7ae17c6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,10 +33,20 @@
 
 #include "stmmac_platform.h"
 
+struct rk_priv_data;
+struct rk_gmac_ops {
+	void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
+			     int tx_delay, int rx_delay);
+	void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
+	void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
+	void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
+};
+
 struct rk_priv_data {
 	struct platform_device *pdev;
 	int phy_iface;
 	struct regulator *regulator;
+	struct rk_gmac_ops *ops;
 
 	bool clk_enabled;
 	bool clock_input;
@@ -66,30 +76,32 @@ struct rk_priv_data {
 #define RK3288_GRF_SOC_CON3	0x0250
 
 /*RK3288_GRF_SOC_CON1*/
-#define GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
-#define GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8))
-#define GMAC_FLOW_CTRL		GRF_BIT(9)
-#define GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
-#define GMAC_SPEED_10M		GRF_CLR_BIT(10)
-#define GMAC_SPEED_100M		GRF_BIT(10)
-#define GMAC_RMII_CLK_25M	GRF_BIT(11)
-#define GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
-#define GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
-#define GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
-#define GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
-#define GMAC_RMII_MODE		GRF_BIT(14)
-#define GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
+#define RK3288_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | \
+					 GRF_CLR_BIT(8))
+#define RK3288_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
+					 GRF_BIT(8))
+#define RK3288_GMAC_FLOW_CTRL		GRF_BIT(9)
+#define RK3288_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
+#define RK3288_GMAC_SPEED_10M		GRF_CLR_BIT(10)
+#define RK3288_GMAC_SPEED_100M		GRF_BIT(10)
+#define RK3288_GMAC_RMII_CLK_25M	GRF_BIT(11)
+#define RK3288_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
+#define RK3288_GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
+#define RK3288_GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
+#define RK3288_GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
+#define RK3288_GMAC_RMII_MODE		GRF_BIT(14)
+#define RK3288_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
 
 /*RK3288_GRF_SOC_CON3*/
-#define GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
-#define GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
-#define GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
-#define GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
-#define GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
-#define GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
-
-static void set_to_rgmii(struct rk_priv_data *bsp_priv,
-			 int tx_delay, int rx_delay)
+#define RK3288_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
+#define RK3288_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
+#define RK3288_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3288_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3288_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
+#define RK3288_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
+
+static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -99,14 +111,16 @@ static void set_to_rgmii(struct rk_priv_data *bsp_priv,
 	}
 
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-		     GMAC_PHY_INTF_SEL_RGMII | GMAC_RMII_MODE_CLR);
+		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
+		     RK3288_GMAC_RMII_MODE_CLR);
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
-		     GMAC_RXCLK_DLY_ENABLE | GMAC_TXCLK_DLY_ENABLE |
-		     GMAC_CLK_RX_DL_CFG(rx_delay) |
-		     GMAC_CLK_TX_DL_CFG(tx_delay));
+		     RK3288_GMAC_RXCLK_DLY_ENABLE |
+		     RK3288_GMAC_TXCLK_DLY_ENABLE |
+		     RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
 }
 
-static void set_to_rmii(struct rk_priv_data *bsp_priv)
+static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -116,10 +130,10 @@ static void set_to_rmii(struct rk_priv_data *bsp_priv)
 	}
 
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-		     GMAC_PHY_INTF_SEL_RMII | GMAC_RMII_MODE);
+		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
 }
 
-static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -129,16 +143,19 @@ static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	}
 
 	if (speed == 10)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_2_5M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_2_5M);
 	else if (speed == 100)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_25M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_25M);
 	else if (speed == 1000)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_125M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_125M);
 	else
 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
 }
 
-static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -149,15 +166,24 @@ static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-			     GMAC_RMII_CLK_2_5M | GMAC_SPEED_10M);
+			     RK3288_GMAC_RMII_CLK_2_5M |
+			     RK3288_GMAC_SPEED_10M);
 	} else if (speed == 100) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-			     GMAC_RMII_CLK_25M | GMAC_SPEED_100M);
+			     RK3288_GMAC_RMII_CLK_25M |
+			     RK3288_GMAC_SPEED_100M);
 	} else {
 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
 	}
 }
 
+struct rk_gmac_ops rk3288_ops = {
+	.set_to_rgmii = rk3288_set_to_rgmii,
+	.set_to_rmii = rk3288_set_to_rmii,
+	.set_rgmii_speed = rk3288_set_rgmii_speed,
+	.set_rmii_speed = rk3288_set_rmii_speed,
+};
+
 static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
@@ -311,7 +337,8 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
 	return 0;
 }
 
-static void *rk_gmac_setup(struct platform_device *pdev)
+static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
+					  struct rk_gmac_ops *ops)
 {
 	struct rk_priv_data *bsp_priv;
 	struct device *dev = &pdev->dev;
@@ -324,6 +351,7 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 		return ERR_PTR(-ENOMEM);
 
 	bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
+	bsp_priv->ops = ops;
 
 	bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
 	if (IS_ERR(bsp_priv->regulator)) {
@@ -378,10 +406,11 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 	/*rmii or rgmii*/
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
 		dev_info(dev, "%s: init for RGMII\n", __func__);
-		set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay);
+		bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
+					    bsp_priv->rx_delay);
 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
 		dev_info(dev, "%s: init for RMII\n", __func__);
-		set_to_rmii(bsp_priv);
+		bsp_priv->ops->set_to_rmii(bsp_priv);
 	} else {
 		dev_err(dev, "%s: NO interface defined!\n", __func__);
 	}
@@ -391,6 +420,11 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 	return bsp_priv;
 }
 
+static void *rk3288_gmac_setup(struct platform_device *pdev)
+{
+	return rk_gmac_setup(pdev, &rk3288_ops);
+}
+
 static int rk_gmac_init(struct platform_device *pdev, void *priv)
 {
 	struct rk_priv_data *bsp_priv = priv;
@@ -421,9 +455,9 @@ static void rk_fix_speed(void *priv, unsigned int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
-		set_rgmii_speed(bsp_priv, speed);
+		bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
 	else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-		set_rmii_speed(bsp_priv, speed);
+		bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
 	else
 		dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
 }
@@ -431,7 +465,7 @@ static void rk_fix_speed(void *priv, unsigned int speed)
 static const struct stmmac_of_data rk3288_gmac_data = {
 	.has_gmac = 1,
 	.fix_mac_speed = rk_fix_speed,
-	.setup = rk_gmac_setup,
+	.setup = rk3288_gmac_setup,
 	.init = rk_gmac_init,
 	.exit = rk_gmac_exit,
 };
-- 
2.1.4



From heiko at sntech.de  Wed Jun 17 14:54:44 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 17 Jun 2015 23:54:44 +0200
Subject: [PATCH 2/4] net: stmmac: dwmac-rk: Fix clk rate when provided by soc
In-Reply-To: <1434578086-12209-1-git-send-email-heiko@sntech.de>
References: <1434578086-12209-1-git-send-email-heiko@sntech.de>
Message-ID: <1434578086-12209-3-git-send-email-heiko@sntech.de>

The first iteration of the dwmac-rk support did access an intermediate
clock directly below the pll selector. This was removed in a subsequent
revision, but the clock and one invocation remained. This results in
the driver trying to set the rate of a non-existent clock when the soc
and not some external source provides the phy clock for RMII phys.

So set the rate of the correct clock and remove the remaining now
completely unused definition.

Fixes: 436f5ae08f9d ("GMAC: add driver for Rockchip RK3288 SoCs integrated GMAC")
Cc: stable at vger.kernel.org
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 49c7715..4faa283 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -42,7 +42,6 @@ struct rk_priv_data {
 	bool clock_input;
 
 	struct clk *clk_mac;
-	struct clk *clk_mac_pll;
 	struct clk *gmac_clkin;
 	struct clk *mac_clk_rx;
 	struct clk *mac_clk_tx;
@@ -209,7 +208,7 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 		dev_info(dev, "%s: clock input from PHY\n", __func__);
 	} else {
 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-			clk_set_rate(bsp_priv->clk_mac_pll, 50000000);
+			clk_set_rate(bsp_priv->clk_mac, 50000000);
 	}
 
 	return 0;
-- 
2.1.4



From heiko at sntech.de  Wed Jun 17 14:54:46 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 17 Jun 2015 23:54:46 +0200
Subject: [PATCH 4/4] net: stmmac: dwmac-rk: add rk3368-specific data
In-Reply-To: <1434578086-12209-1-git-send-email-heiko@sntech.de>
References: <1434578086-12209-1-git-send-email-heiko@sntech.de>
Message-ID: <1434578086-12209-5-git-send-email-heiko@sntech.de>

Add constants and callback functions for the dwmac on rk3368 socs.
As can be seen, the base structure is the same, only registers and
the bits in them moved slightly.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 .../devicetree/bindings/net/rockchip-dwmac.txt     |   2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c     | 126 +++++++++++++++++++++
 2 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
index 21fd199..93eac7c 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
@@ -3,7 +3,7 @@ Rockchip SoC RK3288 10/100/1000 Ethernet driver(GMAC)
 The device node has following properties.
 
 Required properties:
- - compatible: Can be "rockchip,rk3288-gmac".
+ - compatible: Can be one of "rockchip,rk3288-gmac", "rockchip,rk3368-gmac"
  - reg: addresses and length of the register sets for the device.
  - interrupts: Should contain the GMAC interrupts.
  - interrupt-names: Should contain the interrupt names "macirq".
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 7ae17c6..fe08ee7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -184,6 +184,118 @@ struct rk_gmac_ops rk3288_ops = {
 	.set_rmii_speed = rk3288_set_rmii_speed,
 };
 
+#define RK3368_GRF_SOC_CON15	0x043c
+#define RK3368_GRF_SOC_CON16	0x0440
+
+/* RK3368_GRF_SOC_CON15 */
+#define RK3368_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
+					 GRF_CLR_BIT(11))
+#define RK3368_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
+					 GRF_BIT(11))
+#define RK3368_GMAC_FLOW_CTRL		GRF_BIT(8)
+#define RK3368_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
+#define RK3368_GMAC_SPEED_10M		GRF_CLR_BIT(7)
+#define RK3368_GMAC_SPEED_100M		GRF_BIT(7)
+#define RK3368_GMAC_RMII_CLK_25M	GRF_BIT(3)
+#define RK3368_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
+#define RK3368_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
+#define RK3368_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
+#define RK3368_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
+#define RK3368_GMAC_RMII_MODE		GRF_BIT(6)
+#define RK3368_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
+
+/* RK3368_GRF_SOC_CON16 */
+#define RK3368_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
+#define RK3368_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
+#define RK3368_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3368_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3368_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
+#define RK3368_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
+
+static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
+		     RK3368_GMAC_RMII_MODE_CLR);
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
+		     RK3368_GMAC_RXCLK_DLY_ENABLE |
+		     RK3368_GMAC_TXCLK_DLY_ENABLE |
+		     RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
+}
+
+static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	if (speed == 10)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_2_5M);
+	else if (speed == 100)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_25M);
+	else if (speed == 1000)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_125M);
+	else
+		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	if (speed == 10) {
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_RMII_CLK_2_5M |
+			     RK3368_GMAC_SPEED_10M);
+	} else if (speed == 100) {
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_RMII_CLK_25M |
+			     RK3368_GMAC_SPEED_100M);
+	} else {
+		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+	}
+}
+
+struct rk_gmac_ops rk3368_ops = {
+	.set_to_rgmii = rk3368_set_to_rgmii,
+	.set_to_rmii = rk3368_set_to_rmii,
+	.set_rgmii_speed = rk3368_set_rgmii_speed,
+	.set_rmii_speed = rk3368_set_rmii_speed,
+};
+
 static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
@@ -425,6 +537,11 @@ static void *rk3288_gmac_setup(struct platform_device *pdev)
 	return rk_gmac_setup(pdev, &rk3288_ops);
 }
 
+static void *rk3368_gmac_setup(struct platform_device *pdev)
+{
+	return rk_gmac_setup(pdev, &rk3368_ops);
+}
+
 static int rk_gmac_init(struct platform_device *pdev, void *priv)
 {
 	struct rk_priv_data *bsp_priv = priv;
@@ -470,8 +587,17 @@ static const struct stmmac_of_data rk3288_gmac_data = {
 	.exit = rk_gmac_exit,
 };
 
+static const struct stmmac_of_data rk3368_gmac_data = {
+	.has_gmac = 1,
+	.fix_mac_speed = rk_fix_speed,
+	.setup = rk3368_gmac_setup,
+	.init = rk_gmac_init,
+	.exit = rk_gmac_exit,
+};
+
 static const struct of_device_id rk_gmac_dwmac_match[] = {
 	{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data},
+	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_gmac_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
-- 
2.1.4



From heiko at sntech.de  Wed Jun 17 14:54:42 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Wed, 17 Jun 2015 23:54:42 +0200
Subject: [PATCH 0/4] net: stmmac: dwmac-rk: add support for rk3368
Message-ID: <1434578086-12209-1-git-send-email-heiko@sntech.de>

Apart from small cleanups, this series provides support for the dwmac
on the new rk3368 ARM64 soc.

Tested on a R88 board using a RMII phy.

Heiko Stuebner (4):
  net: stmmac: dwmac-rk: remove unused gpio register defines
  net: stmmac: dwmac-rk: Fix clk rate when provided by soc
  net: stmmac: dwmac-rk: abstract access to mac settings in the GRF
  net: stmmac: dwmac-rk: add rk3368-specific data

 .../devicetree/bindings/net/rockchip-dwmac.txt     |   2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c     | 248 +++++++++++++++++----
 2 files changed, 203 insertions(+), 47 deletions(-)

-- 
2.1.4



From dinguyen at opensource.altera.com  Wed Jun 17 15:12:45 2015
From: dinguyen at opensource.altera.com (Dinh Nguyen)
Date: Wed, 17 Jun 2015 17:12:45 -0500
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <20150617213006.GC7557@n2100.arm.linux.org.uk>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
 <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
 <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>
 <20150617213006.GC7557@n2100.arm.linux.org.uk>
Message-ID: <5581F0DD.60408@opensource.altera.com>

On 06/17/2015 04:30 PM, Russell King - ARM Linux wrote:
> On Wed, Jun 17, 2015 at 03:35:13PM -0500, Dinh Nguyen wrote:
>> On Mon, Jun 1, 2015 at 6:50 AM, Geert Uytterhoeven <geert at linux-m68k.org> wrote:
>>> Hi Russell,
>>>
>>> On Mon, Jun 1, 2015 at 12:53 PM, Russell King - ARM Linux
>>> <linux at arm.linux.org.uk> wrote:
>>>> On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
>>>>> FWIW, I have the feeling this has a slight influence on boot reliability on
>>>>> two of my boards:
>>>>>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
>>>>>     its bootloader, seems to have a higher change of booting successfully on
>>>>>     cold boot,
>>>>>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
>>>>>     seems to have a lower chance of booting successfully.
>>>>>
>>>>> No time to spend all week turning this into a statistical significant test
>>>>> project... The reset button is my friend...
>>>>
>>>> Damn it, you sent this right after I merged and pushed out this change in
>>>> my for-arm-soc branch, and was just about to send it to the arm-soc people.
>>>> What excellent timing you have. :)
>>>
>>> Don't worry, I didn't send that email to make you postpone this change.
>>> Giving the fuzziness of reproduction, and the flakiness (esp. on Armadillo)
>>> of the boot loader, and these are old SoCs, please go ahead.
>>>
>>>> What happens on the kzm9g if you revert the mach-shmobile changes?
>>>
>>> Seems to make no difference.
>>>
>>>> For armadillo, do you use the decompressor?  That should be doing all the
>>>> cache cleaning already, prior to the kernel being entered.
>>>
>>> I think so.
>>>
>>> Corruption pattern ranges from lock up, over "Error: unrecognized/unsupported
>>> machine ID", to booting almost completely, but lacking a few devices due to
>>> a corrupted DTB. Been like that as long as I remember, i.e. since I got the
>>> board ca. 1 year ago. Boots fine (100%) with kexec.
>>>
>>
>> It seems like this patch is causing the SoCFPGA to not boot with SMP
>> reliably. About 1 out of every 10 reboots, I'm seeing the boot failure
>> below. The error seems to only happen when I do a cold or warm reboot,
>> but never occurs during a power-up. If I revert this patch, or put
>> back the call to v7_invalidate_l1 in socfpga_secondary_startup , then
>> its able to boot 100% of the time.
> 
> It really sucks that you're only just testing this change now, because
> I've frozen my tree, and removing it for the next merge window is going
> to be an entirely non-trivial matter.  You were copied on the original
> patch, which you failed to test... I can't say I have _much_ sympathy
> for a bug report at this point in time.
> 

I apologize for not catching this error while testing this patch. But I
did test it when you first sent it out..I probably didn't do a stress
test. Sometimes the reboot fails in the 1st attempt, sometimes it fails
in the 9th attempt.

I only caught this error when I was testing my recent changes to use
CPU_METHOD_OF_DECLARE.

For me, I don't think you need to revert this patch or anything, but a
fix can go in for a -rcX?

Dinh



From dinguyen at opensource.altera.com  Wed Jun 17 15:31:30 2015
From: dinguyen at opensource.altera.com (Dinh Nguyen)
Date: Wed, 17 Jun 2015 17:31:30 -0500
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <5581F0DD.60408@opensource.altera.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
 <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
 <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>
 <20150617213006.GC7557@n2100.arm.linux.org.uk>
 <5581F0DD.60408@opensource.altera.com>
Message-ID: <5581F542.708@opensource.altera.com>

On 06/17/2015 05:12 PM, Dinh Nguyen wrote:
> On 06/17/2015 04:30 PM, Russell King - ARM Linux wrote:
>> On Wed, Jun 17, 2015 at 03:35:13PM -0500, Dinh Nguyen wrote:
>>> On Mon, Jun 1, 2015 at 6:50 AM, Geert Uytterhoeven <geert at linux-m68k.org> wrote:
>>>> Hi Russell,
>>>>
>>>> On Mon, Jun 1, 2015 at 12:53 PM, Russell King - ARM Linux
>>>> <linux at arm.linux.org.uk> wrote:
>>>>> On Mon, Jun 01, 2015 at 12:41:01PM +0200, Geert Uytterhoeven wrote:
>>>>>> FWIW, I have the feeling this has a slight influence on boot reliability on
>>>>>> two of my boards:
>>>>>>   - r8a7740/armadillo, which is known to suffer from a cache-related bug in
>>>>>>     its bootloader, seems to have a higher change of booting successfully on
>>>>>>     cold boot,
>>>>>>   - sh73a0/kzm9g, which has known cache-issues with secondary CPU boot up,
>>>>>>     seems to have a lower chance of booting successfully.
>>>>>>
>>>>>> No time to spend all week turning this into a statistical significant test
>>>>>> project... The reset button is my friend...
>>>>>
>>>>> Damn it, you sent this right after I merged and pushed out this change in
>>>>> my for-arm-soc branch, and was just about to send it to the arm-soc people.
>>>>> What excellent timing you have. :)
>>>>
>>>> Don't worry, I didn't send that email to make you postpone this change.
>>>> Giving the fuzziness of reproduction, and the flakiness (esp. on Armadillo)
>>>> of the boot loader, and these are old SoCs, please go ahead.
>>>>
>>>>> What happens on the kzm9g if you revert the mach-shmobile changes?
>>>>
>>>> Seems to make no difference.
>>>>
>>>>> For armadillo, do you use the decompressor?  That should be doing all the
>>>>> cache cleaning already, prior to the kernel being entered.
>>>>
>>>> I think so.
>>>>
>>>> Corruption pattern ranges from lock up, over "Error: unrecognized/unsupported
>>>> machine ID", to booting almost completely, but lacking a few devices due to
>>>> a corrupted DTB. Been like that as long as I remember, i.e. since I got the
>>>> board ca. 1 year ago. Boots fine (100%) with kexec.
>>>>
>>>
>>> It seems like this patch is causing the SoCFPGA to not boot with SMP
>>> reliably. About 1 out of every 10 reboots, I'm seeing the boot failure
>>> below. The error seems to only happen when I do a cold or warm reboot,
>>> but never occurs during a power-up. If I revert this patch, or put
>>> back the call to v7_invalidate_l1 in socfpga_secondary_startup , then
>>> its able to boot 100% of the time.
>>
>> It really sucks that you're only just testing this change now, because
>> I've frozen my tree, and removing it for the next merge window is going
>> to be an entirely non-trivial matter.  You were copied on the original
>> patch, which you failed to test... I can't say I have _much_ sympathy
>> for a bug report at this point in time.
>>
> 
> I apologize for not catching this error while testing this patch. But I
> did test it when you first sent it out..I probably didn't do a stress
> test. Sometimes the reboot fails in the 1st attempt, sometimes it fails
> in the 9th attempt.
> 
> I only caught this error when I was testing my recent changes to use
> CPU_METHOD_OF_DECLARE.
> 
> For me, I don't think you need to revert this patch or anything, but a
> fix can go in for a -rcX?
> 

Also, I am not seeing the error on the SoCFPGA Arria 10 platform at all.
This Arria10 platform is running a different version of bootloader than
the Cyclone5. Although, I also did test with the latest version of
U-Boot on the Cyclone5.

Dinh



From linux at arm.linux.org.uk  Wed Jun 17 15:51:57 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 17 Jun 2015 23:51:57 +0100
Subject: [PATCH] ARM: v7 setup function should invalidate L1 cache
In-Reply-To: <5581F542.708@opensource.altera.com>
References: <E1Yuk8W-0001tC-IK@rmk-PC.arm.linux.org.uk>
 <CAMuHMdX=T3CsLTT95H_07Si6Kd8SRraBfxADpn+VtAF4GmZ=mw@mail.gmail.com>
 <CAMuHMdUQkm_9PhSdGS8j85Uodm-o0jiki=Xh4h59PBShB=rCXw@mail.gmail.com>
 <20150601105319.GQ2067@n2100.arm.linux.org.uk>
 <CAMuHMdUXCy+87-pwLiJ7ynaM1AeFq0f7R3sJ4prdE3QN09z++w@mail.gmail.com>
 <CADhT+wdJX7jMO3_rafrZMeA5ZVMaA6b2U4zkksfJcUjh41mH9A@mail.gmail.com>
 <20150617213006.GC7557@n2100.arm.linux.org.uk>
 <5581F0DD.60408@opensource.altera.com>
 <5581F542.708@opensource.altera.com>
Message-ID: <20150617225157.GD7557@n2100.arm.linux.org.uk>

On Wed, Jun 17, 2015 at 05:31:30PM -0500, Dinh Nguyen wrote:
> Also, I am not seeing the error on the SoCFPGA Arria 10 platform at all.
> This Arria10 platform is running a different version of bootloader than
> the Cyclone5. Although, I also did test with the latest version of
> U-Boot on the Cyclone5.

It _shouldn't_ cause any issue, unless secondary_startup is called with
caches already enabled (which it shouldn't.)

If caches are enabled, that's incredibly dodgy even with the old code -
cache lines could be migrated to the incoming CPU which v7_invalidate_l1()
would then invalidate, resulting in the loss of data in those migrated
cache lines.

If caches are not enabled, this change should have no effect: caches
should not be searched if the C bit is clear, and we still end up
invalidating the local L1 cache later in the normal boot sequence.

(If caches are searched with the C bit clear, and the caches initialise
in an unpredictable state, the ARM ARM requires an implementation specific
routine to be executed immediately on CPU startup.  The idea is that if
this option were to be chosen, the vendor must guarantee a certain code
sequence can't be disrupted by the uninitialised state in the caches,
which, if you're searching the caches for instruction fetches, is pretty
much impossible to guarantee no matter what kind of code sequence you
specify: even the first instruction fetched from the CPU reset vector
could ultimately be sourced from the instruction cache if the i-cache
reports that it thinks it has valid data.)

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From stefan.wahren at i2se.com  Thu Jun 18 00:05:01 2015
From: stefan.wahren at i2se.com (Stefan Wahren)
Date: Thu, 18 Jun 2015 09:05:01 +0200
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <55800070.5030509@linaro.org>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com> <557FEAB2.1040101@linaro.org>
 <557FF50C.10809@rock-chips.com> <55800070.5030509@linaro.org>
Message-ID: <55826D9D.2060106@i2se.com>

Hi Srinivas,

Am 16.06.2015 um 12:54 schrieb Srinivas Kandagatla:
>
>
> On 16/06/15 11:06, Caesar Wang wrote:
>> Hi Srinivas,
>>
>> ? 2015?06?16? 17:21, Srinivas Kandagatla ??:
>>> Hi Stefan,
>>>
>>>
>>> On 16/06/15 09:52, Stefan Wahren wrote:
>>>> Hi Caesar,
>>>>
>>>> [add Maxime and Srinivas]
>>>>
>>>> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>>>>> The original driver is uploaded by Jianqun.
>>>>> Here is his patchs:
>>>>>      https://patchwork.kernel.org/patch/5410341/
>>>>>      https://patchwork.kernel.org/patch/5410351/
>>>>>
>>>>> Jianqun, nevermind!
>>>>> I check-pick it and re-upload the driver for the upstream.
>>>>> e.g.:
>>>>>      Tested by on minnie board.(kernel-4.1-rc8)
>>>>>      cd /sys/devices/platform/ffb40000.efuse
>>>>>      localhost ffb40000.efuse # cat cpu_leakage_show
>>>>>      cpu_version_show
>>>>>      The results:
>>>>>              19
>>>>>              2
>>>>>
>>>>> Changes in v2:
>>>>> - Change the document decription.
>>>>> - Move the efuse driver into driver/soc/vendor.
>>>>> - update the efuse driver.
>>>>> - Add the dts node on RK3288.
>>>>>
>>>>>
>>>>
>>>> i want to mention that there is a upcoming new framework suitable for
>>>> efuse drivers:
>>>>
>>>> https://lkml.org/lkml/2015/5/21/643
>>>>
>>>> Unfortunately i don't know the current development state.
>>>>
>>>
>>> Currently this framework is used by atleast 3 drivers(qcom-tsens,
>>> qcom-cpr, begel-bone-cape manager) which are still floating in the
>>> mailing list.
>>>
>>> I was hoping that these 3 users would getback with tested-by.. which
>>> did not happen for last 3-4 weeks.
>>>
>>> I would appreciate, If you could try framework too, and let me know.
>>

yes i work on OCOTP driver for MXS platform and i will try ...

>
> int rockchip_efuse_reg_read(void *context, unsigned int reg, unsigned
> int *val)
> {
>     /* efuse specific read sequence */
>     ...
> }

I will need a specific read sequence too.

Sorry for these newbie questions:

What data structure does context points to for this reg_read opteration?

Do we need range checking of reg or is it handled by the framework?

Are there any limitation for reg_read regarding sleeping or locking
operations?

In case of a read only driver, is everything handle by devicetree or do
we need an empty write operation?

Best regards
Stefan


From mark.yao at rock-chips.com  Thu Jun 18 00:49:24 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:49:24 +0800
Subject: [PATCH 0/6] drm/rockchip: support yuv overlay and plane scale
Message-ID: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>

This series patches are used for yuv image overlay display.

Rockchip vop support NV11, NV16, NV24 yuv format,
and can scale the image scale 1/8 to 8.

Mark Yao (6):
  drm/rockchip: import dma_buf to gem
  drm/rockchip: vop: optimize virtual stride calculate
  drm/rockchip: vop: fix yuv plane support
  drm/rockchip: vop: support plane scale
  drm/rockchip: vop: switch cursor plane to window 3
  drm/rockchip: vop: default enable win2/3 area0 bit

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c |   45 ++-
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |    5 +-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  445 ++++++++++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   96 ++++++
 5 files changed, 581 insertions(+), 11 deletions(-)

-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:49:27 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:49:27 +0800
Subject: [PATCH 3/6] drm/rockchip: vop: fix yuv plane support
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434613770-6608-4-git-send-email-mark.yao@rock-chips.com>

vop support yuv with NV12, NV16 and NV24, only 2 plane yuv.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   42 ++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3c9f4f3..7d84549 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -373,6 +373,18 @@ static enum vop_data_format vop_convert_format(uint32_t format)
 	}
 }
 
+static bool is_yuv_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static bool is_alpha_support(uint32_t format)
 {
 	switch (format) {
@@ -577,16 +589,21 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	struct vop *vop = to_vop(crtc);
 	struct drm_gem_object *obj;
 	struct rockchip_gem_object *rk_obj;
+	struct drm_gem_object *uv_obj;
+	struct rockchip_gem_object *rk_uv_obj;
 	unsigned long offset;
 	unsigned int actual_w;
 	unsigned int actual_h;
 	unsigned int dsp_stx;
 	unsigned int dsp_sty;
 	unsigned int y_vir_stride;
+	unsigned int uv_vir_stride;
 	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
 	enum vop_data_format format;
 	uint32_t val;
 	bool is_alpha;
+	bool is_yuv;
 	bool visible;
 	int ret;
 	struct drm_rect dest = {
@@ -608,6 +625,12 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	};
 	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
 
+	if (drm_format_num_planes(fb->pixel_format) > 2) {
+		DRM_ERROR("unsupport more than 2 plane format[%08x]\n",
+			  fb->pixel_format);
+		return -EINVAL;
+	}
+
 	ret = drm_plane_helper_check_update(plane, crtc, fb,
 					    &src, &dest, &clip,
 					    DRM_PLANE_HELPER_NO_SCALING,
@@ -624,6 +647,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	if (format < 0)
 		return format;
 
+	is_yuv = is_yuv_support(fb->pixel_format);
+
 	obj = rockchip_fb_get_gem_obj(fb, 0);
 	if (!obj) {
 		DRM_ERROR("fail to get rockchip gem object from framebuffer\n");
@@ -642,10 +667,21 @@ static int vop_update_plane_event(struct drm_plane *plane,
 
 	offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3);
 	offset += (src.y1 >> 16) * fb->pitches[0];
-	yrgb_mst = rk_obj->dma_addr + offset;
 
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 	y_vir_stride = fb->pitches[0] >> 2;
 
+	if (is_yuv) {
+		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+		if (!uv_obj) {
+			DRM_ERROR("fail to get uv object from framebuffer\n");
+			return -EINVAL;
+		}
+		rk_uv_obj = to_rockchip_obj(uv_obj);
+		uv_vir_stride = (fb->pitches[1] >> 2);
+		uv_mst = rk_uv_obj->dma_addr + fb->offsets[1];
+	}
+
 	/*
 	 * If this plane update changes the plane's framebuffer, (or more
 	 * precisely, if this update has a different framebuffer than the last
@@ -681,6 +717,10 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	VOP_WIN_SET(vop, win, format, format);
 	VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride);
 	VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst);
+	if (is_yuv) {
+		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
+		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
+	}
 	val = (actual_h - 1) << 16;
 	val |= (actual_w - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, act_info, val);
-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:49:28 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:49:28 +0800
Subject: [PATCH 4/6] drm/rockchip: vop: support plane scale
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434613770-6608-5-git-send-email-mark.yao@rock-chips.com>

Win_full support 1/8 to 8 scale down/up engine, support
all format scale.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  390 ++++++++++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   96 +++++++
 2 files changed, 483 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7d84549..f573459 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -49,6 +49,8 @@
 
 #define VOP_WIN_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->name, v, RELAXED)
+#define VOP_SCL_SET(x, win, name, v) \
+		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
@@ -163,7 +165,37 @@ struct vop_ctrl {
 	struct vop_reg vpost_st_end;
 };
 
+struct vop_scl_regs {
+	struct vop_reg cbr_vsd_mode;
+	struct vop_reg cbr_vsu_mode;
+	struct vop_reg cbr_hsd_mode;
+	struct vop_reg cbr_ver_scl_mode;
+	struct vop_reg cbr_hor_scl_mode;
+	struct vop_reg yrgb_vsd_mode;
+	struct vop_reg yrgb_vsu_mode;
+	struct vop_reg yrgb_hsd_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg line_load_mode;
+	struct vop_reg cbr_axi_gather_num;
+	struct vop_reg yrgb_axi_gather_num;
+	struct vop_reg vsd_cbr_gt2;
+	struct vop_reg vsd_cbr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+	struct vop_reg cbr_axi_gather_en;
+	struct vop_reg yrgb_axi_gather_en;
+
+	struct vop_reg lb_mode;
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+};
+
 struct vop_win_phy {
+	const struct vop_scl_regs *scl;
 	const uint32_t *data_formats;
 	uint32_t nformats;
 
@@ -212,7 +244,36 @@ static const uint32_t formats_234[] = {
 	DRM_FORMAT_RGB565,
 };
 
+static const struct vop_scl_regs win_full_scl = {
+	.cbr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31),
+	.cbr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30),
+	.cbr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28),
+	.cbr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26),
+	.cbr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24),
+	.yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23),
+	.yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22),
+	.yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20),
+	.yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18),
+	.yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16),
+	.line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15),
+	.cbr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12),
+	.yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8),
+	.vsd_cbr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7),
+	.vsd_cbr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6),
+	.vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5),
+	.vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4),
+	.bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2),
+	.cbr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1),
+	.yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0),
+	.lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5),
+	.scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
 static const struct vop_win_phy win01_data = {
+	.scl = &win_full_scl,
 	.data_formats = formats_01,
 	.nformats = ARRAY_SIZE(formats_01),
 	.enable = VOP_REG(WIN0_CTRL0, 0x1, 0),
@@ -351,6 +412,15 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
 	}
 }
 
+static inline int _get_vskiplines(uint32_t srch, uint32_t dsth)
+{
+	if (srch >= (uint32_t)(4 * dsth * MIN_SCL_FT_AFTER_VSKIP))
+		return 4;
+	else if (srch >= (uint32_t)(2 * dsth * MIN_SCL_FT_AFTER_VSKIP))
+		return 2;
+	return 1;
+}
+
 static enum vop_data_format vop_convert_format(uint32_t format)
 {
 	switch (format) {
@@ -538,6 +608,310 @@ static void vop_disable(struct drm_crtc *crtc)
 	pm_runtime_put(vop->dev);
 }
 
+static int _vop_cal_yrgb_lb_mode(int width)
+{
+	int lb_mode = LB_RGB_1920X5;
+
+	if (width > 2560)
+		lb_mode = LB_RGB_3840X2;
+	else if (width > 1920)
+		lb_mode = LB_RGB_2560X4;
+
+	return lb_mode;
+}
+
+static int _vop_cal_cbcr_lb_mode(int width)
+{
+	int lb_mode = LB_YUV_2560X8;
+
+	if (width > 2560)
+		lb_mode = LB_RGB_3840X2;
+	else if (width > 1920)
+		lb_mode = LB_RGB_2560X4;
+	else if (width > 1280)
+		lb_mode = LB_YUV_3840X5;
+
+	return lb_mode;
+}
+
+static void _vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
+			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+			     uint32_t dst_h, uint32_t pixel_format)
+{
+	uint16_t yrgb_hor_scl_mode = SCALE_NONE;
+	uint16_t yrgb_ver_scl_mode = SCALE_NONE;
+	uint16_t cbr_hor_scl_mode = SCALE_NONE;
+	uint16_t cbr_ver_scl_mode = SCALE_NONE;
+	uint16_t yrgb_hsd_mode = SCALE_DOWN_BIL;
+	uint16_t cbr_hsd_mode = SCALE_DOWN_BIL;
+	uint16_t yrgb_vsd_mode = SCALE_DOWN_BIL;
+	uint16_t cbr_vsd_mode = SCALE_DOWN_BIL;
+	uint16_t yrgb_vsu_mode = SCALE_UP_BIL;
+	uint16_t cbr_vsu_mode = SCALE_UP_BIL;
+	uint16_t scale_yrgb_x = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_yrgb_y = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_cbcr_x = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_cbcr_y = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	int hsub = drm_format_horz_chroma_subsampling(pixel_format);
+	int vsub = drm_format_vert_chroma_subsampling(pixel_format);
+	bool is_yuv = is_yuv_support(pixel_format);
+	uint16_t vsd_yrgb_gt4 = 0;
+	uint16_t vsd_yrgb_gt2 = 0;
+	uint16_t vsd_cbr_gt4 = 0;
+	uint16_t vsd_cbr_gt2 = 0;
+	uint16_t yrgb_src_w = src_w;
+	uint16_t yrgb_src_h = src_h;
+	uint16_t yrgb_dst_w = dst_w;
+	uint16_t yrgb_dst_h = dst_h;
+	uint16_t cbcr_src_w;
+	uint16_t cbcr_src_h;
+	uint16_t cbcr_dst_w;
+	uint16_t cbcr_dst_h;
+	uint32_t vdmult;
+	uint16_t lb_mode;
+
+	if (((yrgb_dst_w << 3) <= yrgb_src_w) ||
+	    ((yrgb_dst_h << 3) <= yrgb_src_h) ||
+	    yrgb_dst_w > 3840) {
+		DRM_ERROR("yrgb scale exceed 8,src[%dx%d] dst[%dx%d]\n",
+			  yrgb_src_w, yrgb_src_h, yrgb_dst_w, yrgb_dst_h);
+		return;
+	}
+
+	if (yrgb_src_w < yrgb_dst_w)
+		yrgb_hor_scl_mode = SCALE_UP;
+	else if (yrgb_src_w > yrgb_dst_w)
+		yrgb_hor_scl_mode = SCALE_DOWN;
+	else
+		yrgb_hor_scl_mode = SCALE_NONE;
+
+	if (yrgb_src_h < yrgb_dst_h)
+		yrgb_ver_scl_mode = SCALE_UP;
+	else if (yrgb_src_h  > yrgb_dst_h)
+		yrgb_ver_scl_mode = SCALE_DOWN;
+	else
+		yrgb_ver_scl_mode = SCALE_NONE;
+
+	if (is_yuv) {
+		cbcr_src_w = src_w / hsub;
+		cbcr_src_h = src_h / vsub;
+		cbcr_dst_w = dst_w;
+		cbcr_dst_h = dst_h;
+		if ((cbcr_dst_w << 3) <= cbcr_src_w ||
+		    (cbcr_dst_h << 3) <= cbcr_src_h ||
+		    cbcr_src_w > 3840 ||
+		    cbcr_src_w == 0)
+			DRM_ERROR("cbcr scale failed,src[%dx%d] dst[%dx%d]\n",
+				  cbcr_src_w, cbcr_src_h,
+				  cbcr_dst_w, cbcr_dst_h);
+		if (cbcr_src_w < cbcr_dst_w)
+			cbr_hor_scl_mode = SCALE_UP;
+		else if (cbcr_src_w > cbcr_dst_w)
+			cbr_hor_scl_mode = SCALE_DOWN;
+
+		if (cbcr_src_h < cbcr_dst_h)
+			cbr_ver_scl_mode = SCALE_UP;
+		else if (cbcr_src_h > cbcr_dst_h)
+			cbr_ver_scl_mode = SCALE_DOWN;
+	}
+	/*
+	 * line buffer mode
+	 */
+	if (is_yuv) {
+		if (yrgb_hor_scl_mode == SCALE_DOWN && yrgb_dst_w > 2560)
+			lb_mode = LB_RGB_3840X2;
+		else if (cbr_hor_scl_mode == SCALE_DOWN)
+			lb_mode = _vop_cal_cbcr_lb_mode(cbcr_dst_w);
+		else
+			lb_mode = _vop_cal_cbcr_lb_mode(cbcr_src_w);
+	} else {
+		if (yrgb_hor_scl_mode == SCALE_DOWN)
+			lb_mode = _vop_cal_yrgb_lb_mode(yrgb_dst_w);
+		else
+			lb_mode = _vop_cal_yrgb_lb_mode(yrgb_src_w);
+	}
+
+	switch (lb_mode) {
+	case LB_YUV_3840X5:
+	case LB_YUV_2560X8:
+	case LB_RGB_1920X5:
+	case LB_RGB_1280X8:
+		yrgb_vsu_mode = SCALE_UP_BIC;
+		cbr_vsu_mode  = SCALE_UP_BIC;
+		break;
+	case LB_RGB_3840X2:
+		if (yrgb_ver_scl_mode != SCALE_NONE)
+			DRM_ERROR("ERROR : not allow yrgb ver scale\n");
+		if (cbr_ver_scl_mode != SCALE_NONE)
+			DRM_ERROR("ERROR : not allow cbcr ver scale\n");
+		break;
+	case LB_RGB_2560X4:
+		yrgb_vsu_mode = SCALE_UP_BIL;
+		cbr_vsu_mode  = SCALE_UP_BIL;
+		break;
+	default:
+		DRM_ERROR("unsupport lb_mode:%d\n", lb_mode);
+		break;
+	}
+	/*
+	 * (1.1)YRGB HOR SCALE FACTOR
+	 */
+	switch (yrgb_hor_scl_mode) {
+	case SCALE_UP:
+		scale_yrgb_x = GET_SCL_FT_BIC(yrgb_src_w, yrgb_dst_w);
+		break;
+	case SCALE_DOWN:
+		switch (yrgb_hsd_mode) {
+		case SCALE_DOWN_BIL:
+			scale_yrgb_x = GET_SCL_FT_BILI_DN(yrgb_src_w,
+							  yrgb_dst_w);
+			break;
+		case SCALE_DOWN_AVG:
+			scale_yrgb_x = GET_SCL_FT_AVRG(yrgb_src_w, yrgb_dst_w);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_hsd_mode:%d\n",
+				  yrgb_hsd_mode);
+			break;
+		}
+		break;
+	}
+
+	/*
+	 * (1.2)YRGB VER SCALE FACTOR
+	 */
+	switch (yrgb_ver_scl_mode) {
+	case SCALE_UP:
+		switch (yrgb_vsu_mode) {
+		case SCALE_UP_BIL:
+			scale_yrgb_y = GET_SCL_FT_BILI_UP(yrgb_src_h,
+							  yrgb_dst_h);
+			break;
+		case SCALE_UP_BIC:
+			if (yrgb_src_h < 3)
+				DRM_ERROR("yrgb_src_h should greater than 3\n");
+			scale_yrgb_y = GET_SCL_FT_BIC(yrgb_src_h, yrgb_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_vsu_mode:%d\n",
+				  yrgb_vsu_mode);
+			break;
+		}
+		break;
+	case SCALE_DOWN:
+		switch (yrgb_vsd_mode) {
+		case SCALE_DOWN_BIL:
+			vdmult = _get_vskiplines(yrgb_src_h, yrgb_dst_h);
+			scale_yrgb_y = GET_SCL_FT_BILI_DN_VSKIP(yrgb_src_h,
+								yrgb_dst_h,
+								vdmult);
+			if (vdmult == 4) {
+				vsd_yrgb_gt4 = 1;
+				vsd_yrgb_gt2 = 0;
+			} else if (vdmult == 2) {
+				vsd_yrgb_gt4 = 0;
+				vsd_yrgb_gt2 = 1;
+			}
+			break;
+		case SCALE_DOWN_AVG:
+			scale_yrgb_y = GET_SCL_FT_AVRG(yrgb_src_h, yrgb_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_vsd_mode:%d\n",
+				  yrgb_vsd_mode);
+			break;
+		}
+		break;
+	}
+	/*
+	 * (2.1)CBCR HOR SCALE FACTOR
+	 */
+	switch (cbr_hor_scl_mode) {
+	case SCALE_UP:
+		scale_cbcr_x = GET_SCL_FT_BIC(cbcr_src_w, cbcr_dst_w);
+		break;
+	case SCALE_DOWN:
+		switch (cbr_hsd_mode) {
+		case SCALE_DOWN_BIL:
+			scale_cbcr_x = GET_SCL_FT_BILI_DN(cbcr_src_w,
+							  cbcr_dst_w);
+			break;
+		case SCALE_DOWN_AVG:
+			scale_cbcr_x = GET_SCL_FT_AVRG(cbcr_src_w, cbcr_dst_w);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_hsd_mode:%d\n", cbr_hsd_mode);
+			break;
+		}
+		break;
+	}
+
+	/*
+	 * (2.2)CBCR VER SCALE FACTOR
+	 */
+	switch (cbr_ver_scl_mode) {
+	case SCALE_UP:
+		switch (cbr_vsu_mode) {
+		case SCALE_UP_BIL:
+			scale_cbcr_y = GET_SCL_FT_BILI_UP(cbcr_src_h,
+							  cbcr_dst_h);
+			break;
+		case SCALE_UP_BIC:
+			if (cbcr_src_h < 3)
+				DRM_ERROR("cbcr_src_h need greater than 3 !\n");
+			scale_cbcr_y = GET_SCL_FT_BIC(cbcr_src_h, cbcr_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_vsu_mode:%d\n", cbr_vsu_mode);
+			break;
+		}
+		break;
+	case SCALE_DOWN:
+		switch (cbr_vsd_mode) {
+		case SCALE_DOWN_BIL:
+			vdmult = _get_vskiplines(cbcr_src_h, cbcr_dst_h);
+			scale_cbcr_y = GET_SCL_FT_BILI_DN_VSKIP(cbcr_src_h,
+								cbcr_dst_h,
+								vdmult);
+			if (vdmult == 4) {
+				vsd_cbr_gt4 = 1;
+				vsd_cbr_gt2 = 0;
+			} else if (vdmult == 2) {
+				vsd_cbr_gt4 = 0;
+				vsd_cbr_gt2 = 1;
+			}
+			break;
+		case SCALE_DOWN_AVG:
+			scale_cbcr_y = GET_SCL_FT_AVRG(cbcr_src_h, cbcr_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_vsd_mode:%d\n", cbr_vsd_mode);
+			break;
+		}
+		break;
+	}
+
+	VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+	VOP_SCL_SET(vop, win, cbr_hor_scl_mode, cbr_hor_scl_mode);
+	VOP_SCL_SET(vop, win, cbr_ver_scl_mode, cbr_ver_scl_mode);
+	VOP_SCL_SET(vop, win, lb_mode, lb_mode);
+	VOP_SCL_SET(vop, win, yrgb_hsd_mode, yrgb_hsd_mode);
+	VOP_SCL_SET(vop, win, cbr_hsd_mode, cbr_hsd_mode);
+	VOP_SCL_SET(vop, win, yrgb_vsd_mode, yrgb_vsd_mode);
+	VOP_SCL_SET(vop, win, cbr_vsd_mode, cbr_vsd_mode);
+	VOP_SCL_SET(vop, win, yrgb_vsu_mode, yrgb_vsu_mode);
+	VOP_SCL_SET(vop, win, cbr_vsu_mode, cbr_vsu_mode);
+	VOP_SCL_SET(vop, win, scale_yrgb_x, scale_yrgb_x);
+	VOP_SCL_SET(vop, win, scale_yrgb_y, scale_yrgb_y);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vsd_yrgb_gt4);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vsd_yrgb_gt2);
+	VOP_SCL_SET(vop, win, scale_cbcr_x, scale_cbcr_x);
+	VOP_SCL_SET(vop, win, scale_cbcr_y, scale_cbcr_y);
+	VOP_SCL_SET(vop, win, vsd_cbr_gt4, vsd_cbr_gt4);
+	VOP_SCL_SET(vop, win, vsd_cbr_gt2, vsd_cbr_gt2);
+}
+
 /*
  * Caller must hold vsync_mutex.
  */
@@ -624,6 +998,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 		.y2 = crtc->mode.vdisplay,
 	};
 	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
+	int min_scale = win->phy->scl ? 0x02000 : DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = win->phy->scl ? 0x80000 : DRM_PLANE_HELPER_NO_SCALING;
 
 	if (drm_format_num_planes(fb->pixel_format) > 2) {
 		DRM_ERROR("unsupport more than 2 plane format[%08x]\n",
@@ -633,8 +1009,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 
 	ret = drm_plane_helper_check_update(plane, crtc, fb,
 					    &src, &dest, &clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
+					    min_scale,
+					    max_scale,
 					    can_position, false, &visible);
 	if (ret)
 		return ret;
@@ -678,7 +1054,7 @@ static int vop_update_plane_event(struct drm_plane *plane,
 			return -EINVAL;
 		}
 		rk_uv_obj = to_rockchip_obj(uv_obj);
-		uv_vir_stride = (fb->pitches[1] >> 2);
+		uv_vir_stride = fb->pitches[1] >> 2;
 		uv_mst = rk_uv_obj->dma_addr + fb->offsets[1];
 	}
 
@@ -721,9 +1097,17 @@ static int vop_update_plane_event(struct drm_plane *plane,
 		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
 		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
 	}
+
+	if (win->phy->scl)
+		_vop_cal_scl_fac(vop, win, actual_w, actual_h,
+				 crtc_w, crtc_h, fb->pixel_format);
+
 	val = (actual_h - 1) << 16;
 	val |= (actual_w - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, act_info, val);
+
+	val = (crtc_h - 1) << 16;
+	val |= (crtc_w - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, dsp_info, val);
 	val = (dsp_sty - 1) << 16;
 	val |= (dsp_stx - 1) & 0xffff;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 63e9b3a..edacdee 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -198,4 +198,100 @@ enum factor_mode {
 	ALPHA_SRC_GLOBAL,
 };
 
+enum scale_mode {
+	SCALE_NONE = 0x0,
+	SCALE_UP   = 0x1,
+	SCALE_DOWN = 0x2
+};
+
+enum lb_mode {
+	LB_YUV_3840X5 = 0x0,
+	LB_YUV_2560X8 = 0x1,
+	LB_RGB_3840X2 = 0x2,
+	LB_RGB_2560X4 = 0x3,
+	LB_RGB_1920X5 = 0x4,
+	LB_RGB_1280X8 = 0x5
+};
+
+enum sacle_up_mode {
+	SCALE_UP_BIL = 0x0,
+	SCALE_UP_BIC = 0x1
+};
+
+enum scale_down_mode {
+	SCALE_DOWN_BIL = 0x0,
+	SCALE_DOWN_AVG = 0x1
+};
+
+#define CUBIC_PRECISE  0
+#define CUBIC_SPLINE   1
+#define CUBIC_CATROM   2
+#define CUBIC_MITCHELL 3
+
+#define CUBIC_MODE_SELETION      CUBIC_PRECISE
+
+#define SCL_FT_BILI_DN_FIXPOINT_SHIFT	12
+#define SCL_FT_BILI_DN_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_FT_BILI_DN_FIXPOINT_SHIFT)))
+
+#define SCL_FT_BILI_UP_FIXPOINT_SHIFT	16
+
+#define SCL_FT_AVRG_FIXPOINT_SHIFT	16
+#define SCL_FT_AVRG_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_FT_AVRG_FIXPOINT_SHIFT)))
+
+#define SCL_FT_BIC_FIXPOINT_SHIFT	16
+#define SCL_FT_BIC_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_FT_BIC_FIXPOINT_SHIFT)))
+
+#define SCL_FT_DEFAULT_FIXPOINT_SHIFT    12
+#define SCL_FT_VSDBIL_FIXPOINT_SHIFT     12
+
+#define SCL_CAL(src, dst, shift) \
+		((((src) * 2 - 3) << ((shift) - 1)) / ((dst) - 1))
+#define GET_SCL_FT_BILI_DN(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BILI_DN_FIXPOINT_SHIFT)
+#define GET_SCL_FT_BILI_UP(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BILI_UP_FIXPOINT_SHIFT)
+#define GET_SCL_FT_BIC(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BIC_FIXPOINT_SHIFT)
+
+#define GET_SCL_DN_ACT_HEIGHT(src_h, vdmult) \
+		(((src_h) + (vdmult) - 1) / (vdmult))
+
+#define MIN_SCL_FT_AFTER_VSKIP	1
+#define GET_SCL_FT_BILI_DN_VSKIP(src_h, dst_h, vdmult) \
+		((GET_SCL_DN_ACT_HEIGHT((src_h), (vdmult)) == (dst_h)) \
+			? (GET_SCL_FT_BILI_DN((src_h), (dst_h))/(vdmult)) \
+			: GET_SCL_FT_BILI_DN(GET_SCL_DN_ACT_HEIGHT((src_h), \
+					     (vdmult)), (dst_h)))
+
+#define GET_SCL_FT_AVRG(src, dst) \
+		(((dst) << ((SCL_FT_AVRG_FIXPOINT_SHIFT) + 1)) \
+		 / (2 * (src) - 1))
+
+#define SCL_COOR_ACC_FIXPOINT_SHIFT	16
+#define SCL_COOR_ACC_FIXPOINT_ONE	(1 << SCL_COOR_ACC_FIXPOINT_SHIFT)
+#define SCL_COOR_ACC_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_COOR_ACC_FIXPOINT_SHIFT)))
+#define SCL_COOR_ACC_FIXPOINT_REVERT(x)	\
+		((((x) >> (SCL_COOR_ACC_FIXPOINT_SHIFT-1)) + 1) >> 1)
+
+#define SCL_GET_COOR_ACC_FIXPOINT(scale, shift)  \
+		((scale) << (SCL_COOR_ACC_FIXPOINT_SHIFT - (shift)))
+#define SCL_FILTER_FT_FIXPOINT_SHIFT	8
+#define SCL_FILTER_FT_FIXPOINT_ONE	(1 << SCL_FILTER_FT_FIXPOINT_SHIFT)
+#define SCL_FILTER_FT_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_FILTER_FT_FIXPOINT_SHIFT)))
+#define SCL_FILTER_FT_FIXPOINT_REVERT(x) \
+		((((x) >> (SCL_FILTER_FT_FIXPOINT_SHIFT - 1)) + 1) >> 1)
+
+#define SCL_GET_FILTER_FT_FIXPOINT(ca, shift) \
+		(((ca) >> ((shift)-SCL_FILTER_FT_FIXPOINT_SHIFT)) & \
+		 (SCL_FILTER_FT_FIXPOINT_ONE - 1))
+
+#define SCL_OFFSET_FIXPOINT_SHIFT	8
+#define SCL_OFFSET_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_OFFSET_FIXPOINT_SHIFT)))
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:49:26 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:49:26 +0800
Subject: [PATCH 2/6] drm/rockchip: vop: optimize virtual stride calculate
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434613770-6608-3-git-send-email-mark.yao@rock-chips.com>

vir_stride need number words of the virtual width, and fb->pitches
save bytes_per_pixel, so just div 4 switch to stride.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 6188221..3c9f4f3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -644,7 +644,7 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	offset += (src.y1 >> 16) * fb->pitches[0];
 	yrgb_mst = rk_obj->dma_addr + offset;
 
-	y_vir_stride = fb->pitches[0] / (fb->bits_per_pixel >> 3);
+	y_vir_stride = fb->pitches[0] >> 2;
 
 	/*
 	 * If this plane update changes the plane's framebuffer, (or more
-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:49:25 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:49:25 +0800
Subject: [PATCH 1/6] drm/rockchip: import dma_buf to gem
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434613770-6608-2-git-send-email-mark.yao@rock-chips.com>

We want to display a buffer allocated by other driver, need import
the buffer to gem.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c |   45 +++++++++++++++++++++++++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |    5 ++-
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 3962176..9001a90 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -287,6 +287,7 @@ static struct drm_driver rockchip_drm_driver = {
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
 	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
 	.gem_prime_export	= drm_gem_prime_export,
 	.gem_prime_get_sg_table	= rockchip_gem_prime_get_sg_table,
 	.gem_prime_vmap		= rockchip_gem_prime_vmap,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index eb2282c..2e30e23 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -18,6 +18,7 @@
 #include <drm/drm_vma_manager.h>
 
 #include <linux/dma-attrs.h>
+#include <linux/dma-buf.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
@@ -105,6 +106,38 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 	return ret;
 }
 
+struct drm_gem_object *
+rockchip_gem_prime_import_sg_table(struct drm_device *drm,
+				   struct dma_buf_attachment *attach,
+				   struct sg_table *sgt)
+{
+	struct rockchip_gem_object *rk_obj;
+	struct drm_gem_object *obj;
+	int ret;
+
+	rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL);
+	if (!rk_obj)
+		return ERR_PTR(-ENOMEM);
+
+	obj = &rk_obj->base;
+
+	drm_gem_private_object_init(drm, obj, attach->dmabuf->size);
+
+	if (!dma_map_sg(drm->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE)) {
+		ret = -ENOMEM;
+		goto err_free_obj;
+	}
+	rk_obj->dma_addr = sg_dma_address(sgt->sgl);
+	rk_obj->sgt = sgt;
+	obj->size = sg_dma_len(sgt->sgl);
+
+	return obj;
+
+err_free_obj:
+	kfree(rk_obj);
+	return ERR_PTR(ret);
+}
+
 struct rockchip_gem_object *
 	rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
 				   bool alloc_kmap)
@@ -140,13 +173,19 @@ err_free_rk_obj:
  */
 void rockchip_gem_free_object(struct drm_gem_object *obj)
 {
+	struct drm_device *drm = obj->dev;
 	struct rockchip_gem_object *rk_obj;
 
-	drm_gem_free_mmap_offset(obj);
-
 	rk_obj = to_rockchip_obj(obj);
 
-	rockchip_gem_free_buf(rk_obj);
+	if (obj->import_attach) {
+		dma_unmap_sg(drm->dev, rk_obj->sgt->sgl,
+			     rk_obj->sgt->nents, DMA_TO_DEVICE);
+		drm_prime_gem_destroy(obj, rk_obj->sgt);
+	} else {
+		drm_gem_free_mmap_offset(obj);
+		rockchip_gem_free_buf(rk_obj);
+	}
 
 	kfree(rk_obj);
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index ad22618..9fd58e3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -21,6 +21,7 @@ struct rockchip_gem_object {
 	struct drm_gem_object base;
 	unsigned int flags;
 
+	struct sg_table *sgt;
 	void *kvaddr;
 	dma_addr_t dma_addr;
 	struct dma_attrs dma_attrs;
@@ -28,8 +29,10 @@ struct rockchip_gem_object {
 
 struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *
-rockchip_gem_prime_import_sg_table(struct drm_device *dev, size_t size,
+rockchip_gem_prime_import_sg_table(struct drm_device *drm,
+				   struct dma_buf_attachment *attach,
 				   struct sg_table *sgt);
+
 void *rockchip_gem_prime_vmap(struct drm_gem_object *obj);
 void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 
-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:53:07 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:53:07 +0800
Subject: [PATCH 5/6] drm/rockchip: vop: switch cursor plane to window 3
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434613987-6713-1-git-send-email-mark.yao@rock-chips.com>

Window 1 support scale and yuv format, it's waste use it for a
cursor, use window 3 is enough.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index f573459..ceac71f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -342,13 +342,14 @@ static const struct vop_reg_data vop_init_reg_table[] = {
 /*
  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
  * special support to get alpha blending working.  For now, just use overlay
- * window 1 for the drm cursor.
+ * window 3 for the drm cursor.
+ *
  */
 static const struct vop_win_data rk3288_vop_win_data[] = {
 	{ .base = 0x00, .phy = &win01_data, .type = DRM_PLANE_TYPE_PRIMARY },
-	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_CURSOR },
+	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_OVERLAY },
 	{ .base = 0x00, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
 	{ .base = 0x00, .phy = &cursor_data, .type = DRM_PLANE_TYPE_OVERLAY },
 };
 
-- 
1.7.9.5




From mark.yao at rock-chips.com  Thu Jun 18 00:55:20 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Thu, 18 Jun 2015 15:55:20 +0800
Subject: [PATCH 6/6] drm/rockchip: vop: default enable win2/3 area0 bit
In-Reply-To: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1434614120-6772-1-git-send-email-mark.yao@rock-chips.com>

Win2/3 support 4 area display, but now havn't found a suitable
way to use it, and it enable by win gate and area gate,
so default enable area0 gate, so that its behaviour just like a
win.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index ceac71f..1b70783 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -337,6 +337,12 @@ static const struct vop_reg_data vop_init_reg_table[] = {
 	{DSP_CTRL0, 0x00000000},
 	{WIN0_CTRL0, 0x00000080},
 	{WIN1_CTRL0, 0x00000080},
+	/*
+	 * Todo: win2/3 support area func, but now havn't found a suitable
+	 * way to use it, so default enable area0 as a win display.
+	 */
+	{WIN2_CTRL0, 0x00000010},
+	{WIN3_CTRL0, 0x00000010},
 };
 
 /*
-- 
1.7.9.5




From srinivas.kandagatla at linaro.org  Thu Jun 18 01:29:31 2015
From: srinivas.kandagatla at linaro.org (Srinivas Kandagatla)
Date: Thu, 18 Jun 2015 09:29:31 +0100
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <55826D9D.2060106@i2se.com>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com> <557FEAB2.1040101@linaro.org>
 <557FF50C.10809@rock-chips.com> <55800070.5030509@linaro.org>
 <55826D9D.2060106@i2se.com>
Message-ID: <5582816B.5020208@linaro.org>



On 18/06/15 08:05, Stefan Wahren wrote:
> Hi Srinivas,
>
> Am 16.06.2015 um 12:54 schrieb Srinivas Kandagatla:
>>
>>
>> On 16/06/15 11:06, Caesar Wang wrote:
>>> Hi Srinivas,
>>>
>>> ? 2015?06?16? 17:21, Srinivas Kandagatla ??:
>>>> Hi Stefan,
>>>>
>>>>
>>>> On 16/06/15 09:52, Stefan Wahren wrote:
>>>>> Hi Caesar,
>>>>>
>>>>> [add Maxime and Srinivas]
>>>>>
>>>>> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>>>>>> The original driver is uploaded by Jianqun.
>>>>>> Here is his patchs:
>>>>>>       https://patchwork.kernel.org/patch/5410341/
>>>>>>       https://patchwork.kernel.org/patch/5410351/
>>>>>>
>>>>>> Jianqun, nevermind!
>>>>>> I check-pick it and re-upload the driver for the upstream.
>>>>>> e.g.:
>>>>>>       Tested by on minnie board.(kernel-4.1-rc8)
>>>>>>       cd /sys/devices/platform/ffb40000.efuse
>>>>>>       localhost ffb40000.efuse # cat cpu_leakage_show
>>>>>>       cpu_version_show
>>>>>>       The results:
>>>>>>               19
>>>>>>               2
>>>>>>
>>>>>> Changes in v2:
>>>>>> - Change the document decription.
>>>>>> - Move the efuse driver into driver/soc/vendor.
>>>>>> - update the efuse driver.
>>>>>> - Add the dts node on RK3288.
>>>>>>
>>>>>>
>>>>>
>>>>> i want to mention that there is a upcoming new framework suitable for
>>>>> efuse drivers:
>>>>>
>>>>> https://lkml.org/lkml/2015/5/21/643
>>>>>
>>>>> Unfortunately i don't know the current development state.
>>>>>
>>>>
>>>> Currently this framework is used by atleast 3 drivers(qcom-tsens,
>>>> qcom-cpr, begel-bone-cape manager) which are still floating in the
>>>> mailing list.
>>>>
>>>> I was hoping that these 3 users would getback with tested-by.. which
>>>> did not happen for last 3-4 weeks.
>>>>
>>>> I would appreciate, If you could try framework too, and let me know.
>>>
>
> yes i work on OCOTP driver for MXS platform and i will try ...
>
>>
>> int rockchip_efuse_reg_read(void *context, unsigned int reg, unsigned
>> int *val)
>> {
>>      /* efuse specific read sequence */
>>      ...
>> }
>
> I will need a specific read sequence too.

You can have a look at 
https://git.linaro.org/people/srinivas.kandagatla/linux.git/blob/b4c3ad253747767511233687436f20144e850d67:/drivers/nvmem/rockchip-efuse.c

I did modify the rockchip driver, which I guess should be very much 
similar to what OCOTP driver would need.


>
> Sorry for these newbie questions:
>
> What data structure does context points to for this reg_read opteration?
>
> Do we need range checking of reg or is it handled by the framework?
>
We already have that in place.

> Are there any limitation for reg_read regarding sleeping or locking
> operations?
There are no limitaions as such from nvmem framework, regmap might have 
limitations w.r.t to sleeping and fast_io, as fast_io would take 
spinlocks, AFAIK the providers would not have fast_io, as they not IO 
devices.
>
> In case of a read only driver, is everything handle by devicetree or do
> we need an empty write operation?
Yes, if you pass read-only flag in the provider, the framework would not 
attempt to even write.

You will find answers to most of your question in the rochip-efuse.c file.


--srini
>
> Best regards
> Stefan
>


From wxt at rock-chips.com  Thu Jun 18 02:08:13 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Thu, 18 Jun 2015 17:08:13 +0800
Subject: [PATCH v2 0/3] Add the efuse driver on rockchip platform
In-Reply-To: <5582816B.5020208@linaro.org>
References: <1434439665-27781-1-git-send-email-wxt@rock-chips.com>
 <557FE3EA.4000306@i2se.com> <557FEAB2.1040101@linaro.org>
 <557FF50C.10809@rock-chips.com> <55800070.5030509@linaro.org>
 <55826D9D.2060106@i2se.com> <5582816B.5020208@linaro.org>
Message-ID: <55828A7D.1080202@rock-chips.com>



? 2015?06?18? 16:29, Srinivas Kandagatla ??:
>
>
> On 18/06/15 08:05, Stefan Wahren wrote:
>> Hi Srinivas,
>>
>> Am 16.06.2015 um 12:54 schrieb Srinivas Kandagatla:
>>>
>>>
>>> On 16/06/15 11:06, Caesar Wang wrote:
>>>> Hi Srinivas,
>>>>
>>>> ? 2015?06?16? 17:21, Srinivas Kandagatla ??:
>>>>> Hi Stefan,
>>>>>
>>>>>
>>>>> On 16/06/15 09:52, Stefan Wahren wrote:
>>>>>> Hi Caesar,
>>>>>>
>>>>>> [add Maxime and Srinivas]
>>>>>>
>>>>>> Am 16.06.2015 um 09:27 schrieb Caesar Wang:
>>>>>>> The original driver is uploaded by Jianqun.
>>>>>>> Here is his patchs:
>>>>>>>       https://patchwork.kernel.org/patch/5410341/
>>>>>>>       https://patchwork.kernel.org/patch/5410351/
>>>>>>>
>>>>>>> Jianqun, nevermind!
>>>>>>> I check-pick it and re-upload the driver for the upstream.
>>>>>>> e.g.:
>>>>>>>       Tested by on minnie board.(kernel-4.1-rc8)
>>>>>>>       cd /sys/devices/platform/ffb40000.efuse
>>>>>>>       localhost ffb40000.efuse # cat cpu_leakage_show
>>>>>>>       cpu_version_show
>>>>>>>       The results:
>>>>>>>               19
>>>>>>>               2
>>>>>>>
>>>>>>> Changes in v2:
>>>>>>> - Change the document decription.
>>>>>>> - Move the efuse driver into driver/soc/vendor.
>>>>>>> - update the efuse driver.
>>>>>>> - Add the dts node on RK3288.
>>>>>>>
>>>>>>>
>>>>>>
>>>>>> i want to mention that there is a upcoming new framework suitable 
>>>>>> for
>>>>>> efuse drivers:
>>>>>>
>>>>>> https://lkml.org/lkml/2015/5/21/643
>>>>>>
>>>>>> Unfortunately i don't know the current development state.
>>>>>>
>>>>>
>>>>> Currently this framework is used by atleast 3 drivers(qcom-tsens,
>>>>> qcom-cpr, begel-bone-cape manager) which are still floating in the
>>>>> mailing list.
>>>>>
>>>>> I was hoping that these 3 users would getback with tested-by.. which
>>>>> did not happen for last 3-4 weeks.
>>>>>
>>>>> I would appreciate, If you could try framework too, and let me know.
>>>>
>>
>> yes i work on OCOTP driver for MXS platform and i will try ...
>>
>>>
>>> int rockchip_efuse_reg_read(void *context, unsigned int reg, unsigned
>>> int *val)
>>> {
>>>      /* efuse specific read sequence */
>>>      ...
>>> }
>>
>> I will need a specific read sequence too.
>
> You can have a look at 
> https://git.linaro.org/people/srinivas.kandagatla/linux.git/blob/b4c3ad253747767511233687436f20144e850d67:/drivers/nvmem/rockchip-efuse.c
>
> I did modify the rockchip driver, which I guess should be very much 
> similar to what OCOTP driver would need.

That rockchip-efuse.c driver shouldn't be work.

An entire 8-bit word of data can be read in one read operation with 
STROBE being high and a proper address
selected (address signals A5~A7 are ?don?t cares?).

That's great if we can get the content from the .reg_read when the 
consumer driver
callback the nvmem_cell_read().

e.g.:
static struct regmap_config rockchip_efuse_regmap_config = {
     .reg_bits = 32,
     .val_bits = 8,
     .reg_stride = 1,
     .reg_read = rockchip_efuse_reg_read,
};
...
/ * consumer driver */
nvmem_cell_get()/nvmem_cell_put();
nvmem_cell_read()/nvmem_cell_write();
........


>
>
>>
>> Sorry for these newbie questions:
>>
>> What data structure does context points to for this reg_read opteration?
>>
>> Do we need range checking of reg or is it handled by the framework?
>>
> We already have that in place.
>
>> Are there any limitation for reg_read regarding sleeping or locking
>> operations?
> There are no limitaions as such from nvmem framework, regmap might 
> have limitations w.r.t to sleeping and fast_io, as fast_io would take 
> spinlocks, AFAIK the providers would not have fast_io, as they not IO 
> devices.
>>
>> In case of a read only driver, is everything handle by devicetree or do
>> we need an empty write operation?
> Yes, if you pass read-only flag in the provider, the framework would 
> not attempt to even write.
>
> You will find answers to most of your question in the rochip-efuse.c 
> file.
>
>
> --srini
>>
>> Best regards
>> Stefan
>>
>
>
>

-- 
Thanks,
- Caesar




From davem at davemloft.net  Thu Jun 18 03:31:51 2015
From: davem at davemloft.net (David Miller)
Date: Thu, 18 Jun 2015 03:31:51 -0700 (PDT)
Subject: [PATCH] net: stmmac: dwmac-rk: Don't add function name in info
 or err messages
In-Reply-To: <1434390259-27145-1-git-send-email-romain.perier@gmail.com>
References: <1434390259-27145-1-git-send-email-romain.perier@gmail.com>
Message-ID: <20150618.033151.447730490306007318.davem@davemloft.net>

From: Romain Perier <romain.perier at gmail.com>
Date: Mon, 15 Jun 2015 17:44:19 +0000

> These kind of informations are only useful for debugging and should not be
> displayed in normal modules message.
> 
> Signed-off-by: Romain Perier <romain.perier at gmail.com>

Applied.


From linux at arm.linux.org.uk  Thu Jun 18 03:57:15 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 18 Jun 2015 11:57:15 +0100
Subject: [PATCH 1/6] drm/rockchip: import dma_buf to gem
In-Reply-To: <1434613770-6608-2-git-send-email-mark.yao@rock-chips.com>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
 <1434613770-6608-2-git-send-email-mark.yao@rock-chips.com>
Message-ID: <20150618105715.GJ7557@n2100.arm.linux.org.uk>

On Thu, Jun 18, 2015 at 03:49:25PM +0800, Mark Yao wrote:
> We want to display a buffer allocated by other driver, need import
> the buffer to gem.
> 
> Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
> ---
>  drivers/gpu/drm/rockchip/rockchip_drm_drv.c |    1 +
>  drivers/gpu/drm/rockchip/rockchip_drm_gem.c |   45 +++++++++++++++++++++++++--
>  drivers/gpu/drm/rockchip/rockchip_drm_gem.h |    5 ++-
>  3 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> index 3962176..9001a90 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
> @@ -287,6 +287,7 @@ static struct drm_driver rockchip_drm_driver = {
>  	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
>  	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
>  	.gem_prime_import	= drm_gem_prime_import,
> +	.gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
>  	.gem_prime_export	= drm_gem_prime_export,
>  	.gem_prime_get_sg_table	= rockchip_gem_prime_get_sg_table,
>  	.gem_prime_vmap		= rockchip_gem_prime_vmap,
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
> index eb2282c..2e30e23 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
> @@ -18,6 +18,7 @@
>  #include <drm/drm_vma_manager.h>
>  
>  #include <linux/dma-attrs.h>
> +#include <linux/dma-buf.h>
>  
>  #include "rockchip_drm_drv.h"
>  #include "rockchip_drm_gem.h"
> @@ -105,6 +106,38 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
>  	return ret;
>  }
>  
> +struct drm_gem_object *
> +rockchip_gem_prime_import_sg_table(struct drm_device *drm,
> +				   struct dma_buf_attachment *attach,
> +				   struct sg_table *sgt)
> +{
> +	struct rockchip_gem_object *rk_obj;
> +	struct drm_gem_object *obj;
> +	int ret;
> +
> +	rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL);
> +	if (!rk_obj)
> +		return ERR_PTR(-ENOMEM);
> +
> +	obj = &rk_obj->base;
> +
> +	drm_gem_private_object_init(drm, obj, attach->dmabuf->size);
> +
> +	if (!dma_map_sg(drm->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE)) {
> +		ret = -ENOMEM;
> +		goto err_free_obj;
> +	}
> +	rk_obj->dma_addr = sg_dma_address(sgt->sgl);
> +	rk_obj->sgt = sgt;
> +	obj->size = sg_dma_len(sgt->sgl);

This is wrong.

First, if you can only cope with a single scatterlist entry, you need to
enforce that.  You can do that in your gem_prime_import_sg_table() method
by checking sgt->nents.

Secondly, you're mapping an already mapped scatterlist - scatterlists
are mapped by the exporter inside dma_buf_map_attachment() for your
device.

Thirdly, I hate drm_gem_prime_import() being used on ARM... it forces
drivers to do something very buggy: the DMA buffer is mapped for DMA
when the buffer is imported.  If the buffer is a write-combine or cached
buffer, writes to the buffer after the import will not become visible to
the display hardware until sometime later (when they're evicted from the
caches and/or pushed out of the bus structure.)  The DMA mapping should
be performed as close to the start of DMA as possible.  However, this is
a long-standing issue I have with dma_buf itself and is not something you
should be too concerned with in your patch.  Just bear it in mind if you
start to see corruption of imported buffers - the answer is not more
dma_map_sg() calls, but to get dma_buf fixed.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From heiko at sntech.de  Thu Jun 18 07:18:28 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:28 +0200
Subject: [PATCH v2 1/9] clk: rockchip: rk3288: add CLK_SET_RATE_PARENT to
 sclk_mac
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-2-git-send-email-heiko@sntech.de>

The dwmac ethernet controller on the rk3288 supports phys connected
via rgmii and rmii. With rgmii phys it is expected that the mac clock
is provided externally while with rmii phys the clock can be external
but also generated from the plls. In the later case it of course needs
be at 50MHz, which gets set from the dwmac_rk driver.
As most devices use a rgmii phy it never surfaced so far that the mac
clk mux, doesn't go up one lever to the pll clock in the rmii case with
internal clock generation, as it is missing the CLK_SET_RATE_PARENT flag,
and thus will not set the correct frequency in most cases.

Fixes: b9e4ba541607 ("clk: rockchip: add clock controller for rk3288")
Cc: stable at vger.kernel.org
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk-rk3288.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 4f817ed..0211162 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -578,7 +578,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
 			RK3288_CLKGATE_CON(2), 5, GFLAGS),
-	MUX(SCLK_MAC, "mac_clk", mux_mac_p, 0,
+	MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(21), 4, 1, MFLAGS),
 	GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
 			RK3288_CLKGATE_CON(5), 3, GFLAGS),
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:30 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:30 +0200
Subject: [PATCH v2 3/9] clk: rockchip: protect register macros against
 multipart values
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-4-git-send-email-heiko@sntech.de>

The macros calculate the correct offset from the id in the parameter.
If this parameter does not consist of a single number, the calculation
will return wrong registers in the best case or create unaligned accesses
in the worst case. So protect the calculations against such values.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 6b09267..92edb5f 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -31,22 +31,22 @@
 		((val) << (shift) | (mask) << ((shift) + 16))
 
 /* register positions shared by RK2928, RK3066 and RK3188 */
-#define RK2928_PLL_CON(x)		(x * 0x4)
+#define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
-#define RK2928_CLKSEL_CON(x)	(x * 0x4 + 0x44)
-#define RK2928_CLKGATE_CON(x)	(x * 0x4 + 0xd0)
+#define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
+#define RK2928_CLKGATE_CON(x)	((x) * 0x4 + 0xd0)
 #define RK2928_GLB_SRST_FST		0x100
 #define RK2928_GLB_SRST_SND		0x104
-#define RK2928_SOFTRST_CON(x)	(x * 0x4 + 0x110)
+#define RK2928_SOFTRST_CON(x)	((x) * 0x4 + 0x110)
 #define RK2928_MISC_CON		0x134
 
 #define RK3288_PLL_CON(x)		RK2928_PLL_CON(x)
 #define RK3288_MODE_CON			0x50
-#define RK3288_CLKSEL_CON(x)		(x * 0x4 + 0x60)
-#define RK3288_CLKGATE_CON(x)		(x * 0x4 + 0x160)
+#define RK3288_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
+#define RK3288_CLKGATE_CON(x)		((x) * 0x4 + 0x160)
 #define RK3288_GLB_SRST_FST		0x1b0
 #define RK3288_GLB_SRST_SND		0x1b4
-#define RK3288_SOFTRST_CON(x)		(x * 0x4 + 0x1b8)
+#define RK3288_SOFTRST_CON(x)		((x) * 0x4 + 0x1b8)
 #define RK3288_MISC_CON			0x1e8
 #define RK3288_SDMMC_CON0		0x200
 #define RK3288_SDMMC_CON1		0x204
@@ -67,7 +67,7 @@ enum rockchip_pll_type {
 	.nr = _nr,				\
 	.nf = _nf,				\
 	.no = _no,				\
-	.bwadj = (_nf >> 1),			\
+	.bwadj = ((_nf) >> 1),			\
 }
 
 #define RK3066_PLL_RATE_BWADJ(_rate, _nr, _nf, _no, _bw)	\
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:29 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:29 +0200
Subject: [PATCH v2 2/9] clk: rockchip: fix faulty vip parent name on rk3288
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-3-git-send-email-heiko@sntech.de>

The video input processor (vip) was called camera interface (cif) on
older socs which seems to have resulted in a copy'n'paste error when
creating the rk3288 camera clocks.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk-rk3288.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 0211162..df9dc96 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -189,7 +189,7 @@ PNAME(mux_uart1_p)	= { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)	= { "uart2_src", "uart2_frac", "xin24m" };
 PNAME(mux_uart3_p)	= { "uart3_src", "uart3_frac", "xin24m" };
 PNAME(mux_uart4_p)	= { "uart4_src", "uart4_frac", "xin24m" };
-PNAME(mux_cif_out_p)	= { "cif_src", "xin24m" };
+PNAME(mux_vip_out_p)	= { "vip_src", "xin24m" };
 PNAME(mux_mac_p)	= { "mac_pll_src", "ext_gmac" };
 PNAME(mux_hsadcout_p)	= { "hsadc_src", "ext_hsadc" };
 PNAME(mux_edp_24m_p)	= { "ext_edp_24m", "xin24m" };
@@ -434,7 +434,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(26), 8, 1, MFLAGS,
 			RK3288_CLKGATE_CON(3), 7, GFLAGS),
-	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0,
+	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
 			RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS),
 
 	DIV(0, "pclk_pd_alive", "gpll", 0,
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:27 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:27 +0200
Subject: [PATCH v2 0/9] clk: rockchip: add support for the clock-tree of the
 rk3368
Message-ID: <1434637116-17124-1-git-send-email-heiko@sntech.de>

This series adds support for the clock controller of rk3368
ARM64 socs.

The first 3 patches are fixes for small issues I found while
building the clocktree. The first one fixes an issue if a rmii
phy is used on the rk3288 and the later two do not harm the
functionality of the older socs, as there is no camera interface
driver in them anyway and the issue with the defines only surfaced
on the rk3368.

Patch 4 then adds a new definition for a branch-type.

Some clocks (mainly the hsadc and camera interfaces) have a phase
inverter connected to the clock that makes it possible to adjust
the clock phase by 180 degrees. Patches 5 and 6 finally add
support for these inverters and add the currently missing
definitions to the already present clock drivers.

Patches 7, 8 and 9 finally add the shared dt-binding header and
the rk3368 clock tree itself. The cpu-clocks in there where
tested sucessfully with the big_little_cpufreq driver.

changes since v1:
- add CLK_SET_RATE_PARENT to sclk_mac to provide sane rates
  when using a rmii phy with soc-side clock generation.
  Both as fix for the 3288 and in the newly added rk3368.


Heiko Stuebner (9):
  clk: rockchip: rk3288: add CLK_SET_RATE_PARENT to sclk_mac
  clk: rockchip: fix faulty vip parent name on rk3288
  clk: rockchip: protect register macros against multipart values
  clk: rockchip: add COMPOSITE_NOGATE_DIVTBL variant
  clk: rockchip: add support for phase inverters
  clk: rockchip: define the inverters of rk3066/rk3188 and rk3288
  dt-bindings: add documentation of rk3668 clock controller
  clk: rockchip: add dt-binding header for rk3368
  clk: rockchip: add rk3368 clock controller

 .../bindings/clock/rockchip,rk3368-cru.txt         |  61 ++
 drivers/clk/rockchip/Makefile                      |   2 +
 drivers/clk/rockchip/clk-inverter.c                | 126 +++
 drivers/clk/rockchip/clk-rk3188.c                  |   9 +-
 drivers/clk/rockchip/clk-rk3288.c                  |  13 +-
 drivers/clk/rockchip/clk-rk3368.c                  | 881 +++++++++++++++++++++
 drivers/clk/rockchip/clk.c                         |   7 +
 drivers/clk/rockchip/clk.h                         |  72 +-
 include/dt-bindings/clock/rk3368-cru.h             | 379 +++++++++
 9 files changed, 1537 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
 create mode 100644 drivers/clk/rockchip/clk-inverter.c
 create mode 100644 drivers/clk/rockchip/clk-rk3368.c
 create mode 100644 include/dt-bindings/clock/rk3368-cru.h

-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:31 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:31 +0200
Subject: [PATCH v2 4/9] clk: rockchip: add COMPOSITE_NOGATE_DIVTBL variant
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-5-git-send-email-heiko@sntech.de>

A clock branch consisting of a mux and divider with non-standard
divider values.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 92edb5f..501f02e 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -308,6 +308,26 @@ struct rockchip_clk_branch {
 		.gate_offset	= -1,				\
 	}
 
+#define COMPOSITE_NOGATE_DIVTBL(_id, cname, pnames, f, mo, ms,	\
+				mw, mf, ds, dw, df, dt)		\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_composite,		\
+		.name		= cname,			\
+		.parent_names	= pnames,			\
+		.num_parents	= ARRAY_SIZE(pnames),		\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.mux_shift	= ms,				\
+		.mux_width	= mw,				\
+		.mux_flags	= mf,				\
+		.div_shift	= ds,				\
+		.div_width	= dw,				\
+		.div_flags	= df,				\
+		.div_table	= dt,				\
+		.gate_offset	= -1,				\
+	}
+
 #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\
 	{							\
 		.id		= _id,				\
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:33 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:33 +0200
Subject: [PATCH v2 6/9] clk: rockchip: define the inverters of rk3066/rk3188
 and rk3288
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-7-git-send-email-heiko@sntech.de>

Both soc series' have inverters on the hsadc and camera interface clock
paths. So define them using the newly added inverter type.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/clk-rk3188.c | 9 ++++++++-
 drivers/clk/rockchip/clk-rk3288.c | 7 ++++++-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index e4f9d47..a9ab4f9 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -235,6 +235,7 @@ static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 /* 2 ^ (val + 1) */
 static struct clk_div_table div_core_peri_t[] = {
@@ -310,6 +311,8 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 
 	GATE(0, "pclkin_cif0", "ext_cif0", 0,
 			RK2928_CLKGATE_CON(3), 3, GFLAGS),
+	INVERTER(0, "pclk_cif0", "pclkin_cif0",
+			RK2928_CLKSEL_CON(30), 8, IFLAGS),
 
 	/*
 	 * the 480m are generated inside the usb block from these clocks,
@@ -334,8 +337,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
 			RK2928_CLKGATE_CON(2), 7, GFLAGS),
-	MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0,
+	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
 			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
 	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
 			RK2928_CLKSEL_CON(24), 8, 8, DFLAGS,
@@ -557,6 +562,8 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 
 	GATE(0, "pclkin_cif1", "ext_cif1", 0,
 			RK2928_CLKGATE_CON(3), 4, GFLAGS),
+	INVERTER(0, "pclk_cif1", "pclkin_cif1",
+			RK2928_CLKSEL_CON(30), 12, IFLAGS),
 
 	COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
 			RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS,
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index df9dc96..a8bad7d 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -223,6 +223,7 @@ static struct clk_div_table div_hclk_cpu_t[] = {
 #define MFLAGS CLK_MUX_HIWORD_MASK
 #define DFLAGS CLK_DIVIDER_HIWORD_MASK
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
 static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	/*
@@ -592,8 +593,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
 			RK3288_CLKGATE_CON(2), 6, GFLAGS),
-	MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0,
+	MUX(0, "sclk_hsadc_out", mux_hsadcout_p, 0,
 			RK3288_CLKSEL_CON(22), 4, 1, MFLAGS),
+	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
+			RK3288_CLKSEL_CON(22), 7, IFLAGS),
 
 	GATE(0, "jtag", "ext_jtag", 0,
 			RK3288_CLKGATE_CON(4), 14, GFLAGS),
@@ -768,7 +771,9 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	 */
 
 	GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS),
+	INVERTER(0, "pclk_vip", "pclk_vip_in", RK3288_CLKSEL_CON(29), 4, IFLAGS),
 	GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS),
+	INVERTER(0, "pclk_isp", "pclk_isp_in", RK3288_CLKSEL_CON(29), 3, IFLAGS),
 };
 
 static const char *const rk3288_critical_clocks[] __initconst = {
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:34 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:34 +0200
Subject: [PATCH v2 7/9] dt-bindings: add documentation of rk3668 clock
 controller
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-8-git-send-email-heiko@sntech.de>

Add the devicetree binding for the cru on the rk3368 which quite similar
structured as previous clock controllers.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
Cc: Rob Herring <robh+dt at kernel.org>
Cc: Pawel Moll <pawel.moll at arm.com>
Cc: Mark Rutland <mark.rutland at arm.com>
Cc: Ian Campbell <ijc+devicetree at hellion.org.uk>
Cc: Kumar Gala <galak at codeaurora.org>
Cc: devicetree at vger.kernel.org
---
 .../bindings/clock/rockchip,rk3368-cru.txt         | 61 ++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt

diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
new file mode 100644
index 0000000..7c8bbcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3368-cru.txt
@@ -0,0 +1,61 @@
+* Rockchip RK3368 Clock and Reset Unit
+
+The RK3368 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3368-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing, pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3368-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_gmac" - external GMAC clock - optional
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+ - "ext_vip" - external VIP clock - optional,
+ - "usbotg_out" - output clock of the pll in the otg phy
+
+Example: Clock controller node:
+
+	cru: clock-controller at ff760000 {
+		compatible = "rockchip,rk3368-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial at 10124000 {
+		compatible = "snps,dw-apb-uart";
+		reg = <0x10124000 0x400>;
+		interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <1>;
+		clocks = <&cru SCLK_UART0>;
+	};
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:32 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:32 +0200
Subject: [PATCH v2 5/9] clk: rockchip: add support for phase inverters
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-6-git-send-email-heiko@sntech.de>

Most Rockchip socs have optional phase inverters connected to some
clocks that move the clock-phase by 180 degrees.
While not having any actual influence on the rate, the inverter
provides its own simple recalc_rate callback as relying on the
fallback in the framework is for "lazy developers" according
to the documentation in the code.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/Makefile       |   1 +
 drivers/clk/rockchip/clk-inverter.c | 126 ++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.c          |   7 ++
 drivers/clk/rockchip/clk.h          |  20 ++++++
 4 files changed, 154 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-inverter.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index 2714097..fd71c7d 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -6,6 +6,7 @@ obj-y	+= clk-rockchip.o
 obj-y	+= clk.o
 obj-y	+= clk-pll.o
 obj-y	+= clk-cpu.o
+obj-y	+= clk-inverter.o
 obj-y	+= clk-mmc-phase.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
diff --git a/drivers/clk/rockchip/clk-inverter.c b/drivers/clk/rockchip/clk-inverter.c
new file mode 100644
index 0000000..db852cd
--- /dev/null
+++ b/drivers/clk/rockchip/clk-inverter.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include "clk.h"
+
+struct rockchip_inv_clock {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	int		shift;
+	int		flags;
+	spinlock_t	*lock;
+};
+
+#define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
+
+#define INVERTER_MASK 0x1
+
+static unsigned long rockchip_inv_recalc(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	return parent_rate;
+}
+
+static int rockchip_inv_get_phase(struct clk_hw *hw)
+{
+	struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+	u32 val;
+
+	val = readl(inv_clock->reg) >> (inv_clock->shift) & INVERTER_MASK;
+	return val ? 180 : 0;
+}
+
+static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
+	u32 val;
+
+	switch (degrees) {
+	case 0:
+		val = 0;
+		break;
+	case 180:
+		val = 1;
+		break;
+	default:
+		pr_err("%s: unsupported phase %d for %s\n",
+		       __func__, degrees, __clk_get_name(hw->clk));
+		return -EINVAL;
+	}
+
+	if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
+		writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
+		       inv_clock->reg);
+	} else {
+		unsigned long flags;
+		u32 reg;
+
+		spin_lock_irqsave(inv_clock->lock, flags);
+
+		reg = readl(inv_clock->reg);
+		reg &= ~BIT(inv_clock->shift);
+		reg |= val;
+		writel(reg, inv_clock->reg);
+
+		spin_unlock_irqrestore(inv_clock->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops rockchip_inv_clk_ops = {
+	.recalc_rate	= rockchip_inv_recalc,
+	.get_phase	= rockchip_inv_get_phase,
+	.set_phase	= rockchip_inv_set_phase,
+};
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+				const char *const *parent_names, u8 num_parents,
+				void __iomem *reg, int shift, int flags,
+				spinlock_t *lock)
+{
+	struct clk_init_data init;
+	struct rockchip_inv_clock *inv_clock;
+	struct clk *clk;
+
+	inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
+	if (!inv_clock)
+		return NULL;
+
+	init.num_parents = num_parents;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = parent_names;
+	init.ops = &rockchip_inv_clk_ops;
+
+	inv_clock->hw.init = &init;
+	inv_clock->reg = reg;
+	inv_clock->shift = shift;
+	inv_clock->flags = flags;
+	inv_clock->lock = lock;
+
+	if (name)
+		init.name = name;
+
+	clk = clk_register(NULL, &inv_clock->hw);
+	if (IS_ERR(clk))
+		goto err_free;
+
+	return clk;
+
+err_free:
+	kfree(inv_clock);
+	return NULL;
+}
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 052b94d..2493881 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -277,6 +277,13 @@ void __init rockchip_clk_register_branches(
 				list->div_shift
 			);
 			break;
+		case branch_inverter:
+			clk = rockchip_clk_register_inverter(
+				list->name, list->parent_names,
+				list->num_parents,
+				reg_base + list->muxdiv_offset,
+				list->div_shift, list->div_flags, &clk_lock);
+			break;
 		}
 
 		/* none of the cases above matched */
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index 501f02e..b72dad0 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -182,6 +182,13 @@ struct clk *rockchip_clk_register_mmc(const char *name,
 				const char *const *parent_names, u8 num_parents,
 				void __iomem *reg, int shift);
 
+#define ROCKCHIP_INVERTER_HIWORD_MASK	BIT(0)
+
+struct clk *rockchip_clk_register_inverter(const char *name,
+				const char *const *parent_names, u8 num_parents,
+				void __iomem *reg, int shift, int flags,
+				spinlock_t *lock);
+
 #define PNAME(x) static const char *const x[] __initconst
 
 enum rockchip_clk_branch_type {
@@ -191,6 +198,7 @@ enum rockchip_clk_branch_type {
 	branch_fraction_divider,
 	branch_gate,
 	branch_mmc,
+	branch_inverter,
 };
 
 struct rockchip_clk_branch {
@@ -414,6 +422,18 @@ struct rockchip_clk_branch {
 		.div_shift	= shift,			\
 	}
 
+#define INVERTER(_id, cname, pname, io, is, if)			\
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_inverter,		\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.muxdiv_offset	= io,				\
+		.div_shift	= is,				\
+		.div_flags	= if,				\
+	}
+
 void rockchip_clk_init(struct device_node *np, void __iomem *base,
 		       unsigned long nr_clks);
 struct regmap *rockchip_clk_get_grf(void);
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:35 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:35 +0200
Subject: [PATCH v2 8/9] clk: rockchip: add dt-binding header for rk3368
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-9-git-send-email-heiko@sntech.de>

Add the dt-bindings header for the rk3368, that gets shared between
the clock controller and the clock references in the dts.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 include/dt-bindings/clock/rk3368-cru.h | 379 +++++++++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)
 create mode 100644 include/dt-bindings/clock/rk3368-cru.h

diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h
new file mode 100644
index 0000000..6280753
--- /dev/null
+++ b/include/dt-bindings/clock/rk3368-cru.h
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+/* core clocks */
+#define PLL_APLLB		1
+#define PLL_APLLL		2
+#define PLL_DPLL		3
+#define PLL_CPLL		4
+#define PLL_GPLL		5
+#define PLL_NPLL		6
+#define ARMCLKB			7
+#define ARMCLKL			8
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU_CORE		64
+#define SCLK_SPI0		65
+#define SCLK_SPI1		66
+#define SCLK_SPI2		67
+#define SCLK_SDMMC		68
+#define SCLK_SDIO0		69
+#define SCLK_EMMC		71
+#define SCLK_TSADC		72
+#define SCLK_SARADC		73
+#define SCLK_NANDC0		75
+#define SCLK_UART0		77
+#define SCLK_UART1		78
+#define SCLK_UART2		79
+#define SCLK_UART3		80
+#define SCLK_UART4		81
+#define SCLK_I2S_8CH		82
+#define SCLK_SPDIF_8CH		83
+#define SCLK_I2S_2CH		84
+#define SCLK_TIMER0		85
+#define SCLK_TIMER1		86
+#define SCLK_TIMER2		87
+#define SCLK_TIMER3		88
+#define SCLK_TIMER4		89
+#define SCLK_TIMER5		90
+#define SCLK_TIMER6		91
+#define SCLK_OTGPHY0		93
+#define SCLK_OTG_ADP		96
+#define SCLK_HSICPHY480M	97
+#define SCLK_HSICPHY12M		98
+#define SCLK_MACREF		99
+#define SCLK_VOP0_PWM		100
+#define SCLK_MAC_RX		102
+#define SCLK_MAC_TX		103
+#define SCLK_EDP_24M		104
+#define SCLK_EDP		105
+#define SCLK_RGA		106
+#define SCLK_ISP		107
+#define SCLK_HDCP		108
+#define SCLK_HDMI_HDCP		109
+#define SCLK_HDMI_CEC		110
+#define SCLK_HEVC_CABAC		111
+#define SCLK_HEVC_CORE		112
+#define SCLK_I2S_8CH_OUT	113
+#define SCLK_SDMMC_DRV		114
+#define SCLK_SDIO0_DRV		115
+#define SCLK_EMMC_DRV		117
+#define SCLK_SDMMC_SAMPLE	118
+#define SCLK_SDIO0_SAMPLE	119
+#define SCLK_EMMC_SAMPLE	121
+#define SCLK_USBPHY480M		122
+#define SCLK_PVTM_CORE		123
+#define SCLK_PVTM_GPU		124
+#define SCLK_PVTM_PMU		125
+#define SCLK_SFC		126
+#define SCLK_MAC		127
+#define SCLK_MACREF_OUT		128
+
+#define DCLK_VOP		190
+#define MCLK_CRYPTO		191
+
+/* aclk gates */
+#define ACLK_GPU_MEM		192
+#define ACLK_GPU_CFG		193
+#define ACLK_DMAC_BUS		194
+#define ACLK_DMAC_PERI		195
+#define ACLK_PERI_MMU		196
+#define ACLK_GMAC		197
+#define ACLK_VOP		198
+#define ACLK_VOP_IEP		199
+#define ACLK_RGA		200
+#define ACLK_HDCP		201
+#define ACLK_IEP		202
+#define ACLK_VIO0_NOC		203
+#define ACLK_VIP		204
+#define ACLK_ISP		205
+#define ACLK_VIO1_NOC		206
+#define ACLK_VIDEO		208
+#define ACLK_BUS		209
+#define ACLK_PERI		210
+
+/* pclk gates */
+#define PCLK_GPIO0		320
+#define PCLK_GPIO1		321
+#define PCLK_GPIO2		322
+#define PCLK_GPIO3		323
+#define PCLK_PMUGRF		324
+#define PCLK_MAILBOX		325
+#define PCLK_GRF		329
+#define PCLK_SGRF		330
+#define PCLK_PMU		331
+#define PCLK_I2C0		332
+#define PCLK_I2C1		333
+#define PCLK_I2C2		334
+#define PCLK_I2C3		335
+#define PCLK_I2C4		336
+#define PCLK_I2C5		337
+#define PCLK_SPI0		338
+#define PCLK_SPI1		339
+#define PCLK_SPI2		340
+#define PCLK_UART0		341
+#define PCLK_UART1		342
+#define PCLK_UART2		343
+#define PCLK_UART3		344
+#define PCLK_UART4		345
+#define PCLK_TSADC		346
+#define PCLK_SARADC		347
+#define PCLK_SIM		348
+#define PCLK_GMAC		349
+#define PCLK_PWM0		350
+#define PCLK_PWM1		351
+#define PCLK_TIMER0		353
+#define PCLK_TIMER1		354
+#define PCLK_EDP_CTRL		355
+#define PCLK_MIPI_DSI0		356
+#define PCLK_MIPI_CSI		358
+#define PCLK_HDCP		359
+#define PCLK_HDMI_CTRL		360
+#define PCLK_VIO_H2P		361
+#define PCLK_BUS		362
+#define PCLK_PERI		363
+#define PCLK_DDRUPCTL		364
+#define PCLK_DDRPHY		365
+#define PCLK_ISP		366
+#define PCLK_VIP		367
+#define PCLK_WDT		368
+
+/* hclk gates */
+#define HCLK_SFC		448
+#define HCLK_OTG0		449
+#define HCLK_HOST0		450
+#define HCLK_HOST1		451
+#define HCLK_HSIC		452
+#define HCLK_NANDC0		453
+#define HCLK_TSP		455
+#define HCLK_SDMMC		456
+#define HCLK_SDIO0		457
+#define HCLK_EMMC		459
+#define HCLK_HSADC		460
+#define HCLK_CRYPTO		461
+#define HCLK_I2S_2CH		462
+#define HCLK_I2S_8CH		463
+#define HCLK_SPDIF		464
+#define HCLK_VOP		465
+#define HCLK_ROM		467
+#define HCLK_IEP		468
+#define HCLK_ISP		469
+#define HCLK_RGA		470
+#define HCLK_VIO_AHB_ARBI	471
+#define HCLK_VIO_NOC		472
+#define HCLK_VIP		473
+#define HCLK_VIO_H2P		474
+#define HCLK_VIO_HDCPMMU	475
+#define HCLK_VIDEO		476
+#define HCLK_BUS		477
+#define HCLK_PERI		478
+
+#define CLK_NR_CLKS		(HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE_B0		0
+#define SRST_CORE_B1		1
+#define SRST_CORE_B2		2
+#define SRST_CORE_B3		3
+#define SRST_CORE_B0_PO		4
+#define SRST_CORE_B1_PO		5
+#define SRST_CORE_B2_PO		6
+#define SRST_CORE_B3_PO		7
+#define SRST_L2_B		8
+#define SRST_ADB_B		9
+#define SRST_PD_CORE_B_NIU	10
+#define SRST_PDBUS_STRSYS	11
+#define SRST_SOCDBG_B		14
+#define SRST_CORE_B_DBG		15
+
+#define SRST_DMAC1		18
+#define SRST_INTMEM		19
+#define SRST_ROM		20
+#define SRST_SPDIF8CH		21
+#define SRST_I2S8CH		23
+#define SRST_MAILBOX		24
+#define SRST_I2S2CH		25
+#define SRST_EFUSE_256		26
+#define SRST_MCU_SYS		28
+#define SRST_MCU_PO		29
+#define SRST_MCU_NOC		30
+#define SRST_EFUSE		31
+
+#define SRST_GPIO0		32
+#define SRST_GPIO1		33
+#define SRST_GPIO2		34
+#define SRST_GPIO3		35
+#define SRST_GPIO4		36
+#define SRST_PMUGRF		41
+#define SRST_I2C0		42
+#define SRST_I2C1		43
+#define SRST_I2C2		44
+#define SRST_I2C3		45
+#define SRST_I2C4		46
+#define SRST_I2C5		47
+
+#define SRST_DWPWM		48
+#define SRST_MMC_PERI		49
+#define SRST_PERIPH_MMU		50
+#define SRST_GRF		55
+#define SRST_PMU		56
+#define SRST_PERIPH_AXI		57
+#define SRST_PERIPH_AHB		58
+#define SRST_PERIPH_APB		59
+#define SRST_PERIPH_NIU		60
+#define SRST_PDPERI_AHB_ARBI	61
+#define SRST_EMEM		62
+#define SRST_USB_PERI		63
+
+#define SRST_DMAC2		64
+#define SRST_MAC		66
+#define SRST_GPS		67
+#define SRST_RKPWM		69
+#define SRST_USBHOST0		72
+#define SRST_HSIC		73
+#define SRST_HSIC_AUX		74
+#define SRST_HSIC_PHY		75
+#define SRST_HSADC		76
+#define SRST_NANDC0		77
+#define SRST_SFC		79
+
+#define SRST_SPI0		83
+#define SRST_SPI1		84
+#define SRST_SPI2		85
+#define SRST_SARADC		87
+#define SRST_PDALIVE_NIU	88
+#define SRST_PDPMU_INTMEM	89
+#define SRST_PDPMU_NIU		90
+#define SRST_SGRF		91
+
+#define SRST_VIO_ARBI		96
+#define SRST_RGA_NIU		97
+#define SRST_VIO0_NIU_AXI	98
+#define SRST_VIO_NIU_AHB	99
+#define SRST_LCDC0_AXI		100
+#define SRST_LCDC0_AHB		101
+#define SRST_LCDC0_DCLK		102
+#define SRST_VIP		104
+#define SRST_RGA_CORE		105
+#define SRST_IEP_AXI		106
+#define SRST_IEP_AHB		107
+#define SRST_RGA_AXI		108
+#define SRST_RGA_AHB		109
+#define SRST_ISP		110
+#define SRST_EDP_24M		111
+
+#define SRST_VIDEO_AXI		112
+#define SRST_VIDEO_AHB		113
+#define SRST_MIPIDPHYTX		114
+#define SRST_MIPIDSI0		115
+#define SRST_MIPIDPHYRX		116
+#define SRST_MIPICSI		117
+#define SRST_GPU		120
+#define SRST_HDMI		121
+#define SRST_EDP		122
+#define SRST_PMU_PVTM		123
+#define SRST_CORE_PVTM		124
+#define SRST_GPU_PVTM		125
+#define SRST_GPU_SYS		126
+#define SRST_GPU_MEM_NIU	127
+
+#define SRST_MMC0		128
+#define SRST_SDIO0		129
+#define SRST_EMMC		131
+#define SRST_USBOTG_AHB		132
+#define SRST_USBOTG_PHY		133
+#define SRST_USBOTG_CON		134
+#define SRST_USBHOST0_AHB	135
+#define SRST_USBHOST0_PHY	136
+#define SRST_USBHOST0_CON	137
+#define SRST_USBOTG_UTMI	138
+#define SRST_USBHOST1_UTMI	139
+#define SRST_USB_ADP		141
+
+#define SRST_CORESIGHT		144
+#define SRST_PD_CORE_AHB_NOC	145
+#define SRST_PD_CORE_APB_NOC	146
+#define SRST_GIC		148
+#define SRST_LCDC_PWM0		149
+#define SRST_RGA_H2P_BRG	153
+#define SRST_VIDEO		154
+#define SRST_GPU_CFG_NIU	157
+#define SRST_TSADC		159
+
+#define SRST_DDRPHY0		160
+#define SRST_DDRPHY0_APB	161
+#define SRST_DDRCTRL0		162
+#define SRST_DDRCTRL0_APB	163
+#define SRST_VIDEO_NIU		165
+#define SRST_VIDEO_NIU_AHB	167
+#define SRST_DDRMSCH0		170
+#define SRST_PDBUS_AHB		173
+#define SRST_CRYPTO		174
+
+#define SRST_UART0		179
+#define SRST_UART1		180
+#define SRST_UART2		181
+#define SRST_UART3		182
+#define SRST_UART4		183
+#define SRST_SIMC		186
+#define SRST_TSP		188
+#define SRST_TSP_CLKIN0		189
+
+#define SRST_CORE_L0		192
+#define SRST_CORE_L1		193
+#define SRST_CORE_L2		194
+#define SRST_CORE_L3		195
+#define SRST_CORE_L0_PO		195
+#define SRST_CORE_L1_PO		197
+#define SRST_CORE_L2_PO		198
+#define SRST_CORE_L3_PO		199
+#define SRST_L2_L		200
+#define SRST_ADB_L		201
+#define SRST_PD_CORE_L_NIU	202
+#define SRST_CCI_SYS		203
+#define SRST_CCI_DDR		204
+#define SRST_CCI		205
+#define SRST_SOCDBG_L		206
+#define SRST_CORE_L_DBG		207
+
+#define SRST_CORE_B0_NC		208
+#define SRST_CORE_B0_PO_NC	209
+#define SRST_L2_B_NC		210
+#define SRST_ADB_B_NC		211
+#define SRST_PD_CORE_B_NIU_NC	212
+#define SRST_PDBUS_STRSYS_NC	213
+#define SRST_CORE_L0_NC		214
+#define SRST_CORE_L0_PO_NC	215
+#define SRST_L2_L_NC		216
+#define SRST_ADB_L_NC		217
+#define SRST_PD_CORE_L_NIU_NC	218
+#define SRST_CCI_SYS_NC		219
+#define SRST_CCI_DDR_NC		220
+#define SRST_CCI_NC		221
+#define SRST_TRACE_NC		222
+
+#define SRST_TIMER00		224
+#define SRST_TIMER01		225
+#define SRST_TIMER02		226
+#define SRST_TIMER03		227
+#define SRST_TIMER04		228
+#define SRST_TIMER05		229
+#define SRST_TIMER10		230
+#define SRST_TIMER11		231
+#define SRST_TIMER12		232
+#define SRST_TIMER13		233
+#define SRST_TIMER14		234
+#define SRST_TIMER15		235
+#define SRST_TIMER0_APB		236
+#define SRST_TIMER1_APB		237
-- 
2.1.4



From heiko at sntech.de  Thu Jun 18 07:18:36 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Thu, 18 Jun 2015 16:18:36 +0200
Subject: [PATCH v2 9/9] clk: rockchip: add rk3368 clock controller
In-Reply-To: <1434637116-17124-1-git-send-email-heiko@sntech.de>
References: <1434637116-17124-1-git-send-email-heiko@sntech.de>
Message-ID: <1434637116-17124-10-git-send-email-heiko@sntech.de>

Describe the clock tree and software resets of the rk3368 ARM64 SoC

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/clk/rockchip/Makefile     |   1 +
 drivers/clk/rockchip/clk-rk3368.c | 881 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/rockchip/clk.h        |  16 +
 3 files changed, 898 insertions(+)
 create mode 100644 drivers/clk/rockchip/clk-rk3368.c

diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index fd71c7d..b27edd6 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3288.o
+obj-y	+= clk-rk3368.o
diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c
new file mode 100644
index 0000000..f326ecc
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3368.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/rk3368-cru.h>
+#include "clk.h"
+
+#define RK3368_GRF_SOC_STATUS0	0x480
+
+enum rk3368_plls {
+	apllb, aplll, dpll, cpll, gpll, npll,
+};
+
+static struct rockchip_pll_rate_table rk3368_pll_rates[] = {
+	RK3066_PLL_RATE(2208000000, 1, 92, 1),
+	RK3066_PLL_RATE(2184000000, 1, 91, 1),
+	RK3066_PLL_RATE(2160000000, 1, 90, 1),
+	RK3066_PLL_RATE(2136000000, 1, 89, 1),
+	RK3066_PLL_RATE(2112000000, 1, 88, 1),
+	RK3066_PLL_RATE(2088000000, 1, 87, 1),
+	RK3066_PLL_RATE(2064000000, 1, 86, 1),
+	RK3066_PLL_RATE(2040000000, 1, 85, 1),
+	RK3066_PLL_RATE(2016000000, 1, 84, 1),
+	RK3066_PLL_RATE(1992000000, 1, 83, 1),
+	RK3066_PLL_RATE(1968000000, 1, 82, 1),
+	RK3066_PLL_RATE(1944000000, 1, 81, 1),
+	RK3066_PLL_RATE(1920000000, 1, 80, 1),
+	RK3066_PLL_RATE(1896000000, 1, 79, 1),
+	RK3066_PLL_RATE(1872000000, 1, 78, 1),
+	RK3066_PLL_RATE(1848000000, 1, 77, 1),
+	RK3066_PLL_RATE(1824000000, 1, 76, 1),
+	RK3066_PLL_RATE(1800000000, 1, 75, 1),
+	RK3066_PLL_RATE(1776000000, 1, 74, 1),
+	RK3066_PLL_RATE(1752000000, 1, 73, 1),
+	RK3066_PLL_RATE(1728000000, 1, 72, 1),
+	RK3066_PLL_RATE(1704000000, 1, 71, 1),
+	RK3066_PLL_RATE(1680000000, 1, 70, 1),
+	RK3066_PLL_RATE(1656000000, 1, 69, 1),
+	RK3066_PLL_RATE(1632000000, 1, 68, 1),
+	RK3066_PLL_RATE(1608000000, 1, 67, 1),
+	RK3066_PLL_RATE(1560000000, 1, 65, 1),
+	RK3066_PLL_RATE(1512000000, 1, 63, 1),
+	RK3066_PLL_RATE(1488000000, 1, 62, 1),
+	RK3066_PLL_RATE(1464000000, 1, 61, 1),
+	RK3066_PLL_RATE(1440000000, 1, 60, 1),
+	RK3066_PLL_RATE(1416000000, 1, 59, 1),
+	RK3066_PLL_RATE(1392000000, 1, 58, 1),
+	RK3066_PLL_RATE(1368000000, 1, 57, 1),
+	RK3066_PLL_RATE(1344000000, 1, 56, 1),
+	RK3066_PLL_RATE(1320000000, 1, 55, 1),
+	RK3066_PLL_RATE(1296000000, 1, 54, 1),
+	RK3066_PLL_RATE(1272000000, 1, 53, 1),
+	RK3066_PLL_RATE(1248000000, 1, 52, 1),
+	RK3066_PLL_RATE(1224000000, 1, 51, 1),
+	RK3066_PLL_RATE(1200000000, 1, 50, 1),
+	RK3066_PLL_RATE(1176000000, 1, 49, 1),
+	RK3066_PLL_RATE(1128000000, 1, 47, 1),
+	RK3066_PLL_RATE(1104000000, 1, 46, 1),
+	RK3066_PLL_RATE(1008000000, 1, 84, 2),
+	RK3066_PLL_RATE( 912000000, 1, 76, 2),
+	RK3066_PLL_RATE( 888000000, 1, 74, 2),
+	RK3066_PLL_RATE( 816000000, 1, 68, 2),
+	RK3066_PLL_RATE( 792000000, 1, 66, 2),
+	RK3066_PLL_RATE( 696000000, 1, 58, 2),
+	RK3066_PLL_RATE( 672000000, 1, 56, 2),
+	RK3066_PLL_RATE( 648000000, 1, 54, 2),
+	RK3066_PLL_RATE( 624000000, 1, 52, 2),
+	RK3066_PLL_RATE( 600000000, 1, 50, 2),
+	RK3066_PLL_RATE( 576000000, 1, 48, 2),
+	RK3066_PLL_RATE( 552000000, 1, 46, 2),
+	RK3066_PLL_RATE( 528000000, 1, 88, 4),
+	RK3066_PLL_RATE( 504000000, 1, 84, 4),
+	RK3066_PLL_RATE( 480000000, 1, 80, 4),
+	RK3066_PLL_RATE( 456000000, 1, 76, 4),
+	RK3066_PLL_RATE( 408000000, 1, 68, 4),
+	RK3066_PLL_RATE( 312000000, 1, 52, 4),
+	RK3066_PLL_RATE( 252000000, 1, 84, 8),
+	RK3066_PLL_RATE( 216000000, 1, 72, 8),
+	RK3066_PLL_RATE( 126000000, 2, 84, 8),
+	RK3066_PLL_RATE(  48000000, 2, 32, 8),
+	{ /* sentinel */ },
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin32k" };
+PNAME(mux_armclkb_p)		= { "apllb_core", "gpllb_core" };
+PNAME(mux_armclkl_p)		= { "aplll_core", "gplll_core" };
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr" };
+PNAME(mux_cs_src_p)		= { "apllb_cs", "aplll_cs", "gpll_cs"};
+PNAME(mux_aclk_bus_src_p)	= { "cpll_aclk_bus", "gpll_aclk_bus" };
+
+PNAME(mux_pll_src_cpll_gpll_p)		= { "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_npll_p)	= { "cpll", "gpll", "npll" };
+PNAME(mux_pll_src_npll_cpll_gpll_p)	= { "npll", "cpll", "gpll" };
+PNAME(mux_pll_src_cpll_gpll_usb_p)	= { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_usb_p)	= { "cpll", "gpll", "usbphy_480m",
+					    "usbphy_480m" };
+PNAME(mux_pll_src_cpll_gpll_usb_npll_p)	= { "cpll", "gpll", "usbphy_480m",
+					    "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_npll_p) = { "cpll", "gpll", "npll", "npll" };
+PNAME(mux_pll_src_cpll_gpll_npll_usb_p) = { "cpll", "gpll", "npll",
+					    "usbphy_480m" };
+
+PNAME(mux_i2s_8ch_pre_p)	= { "i2s_8ch_src", "i2s_8ch_frac",
+				    "ext_i2s", "xin12m" };
+PNAME(mux_i2s_8ch_clkout_p)	= { "i2s_8ch_pre", "xin12m" };
+PNAME(mux_i2s_2ch_p)		= { "i2s_2ch_src", "i2s_2ch_frac",
+				    "dummy", "xin12m" };
+PNAME(mux_spdif_8ch_p)		= { "spdif_8ch_pre", "spdif_8ch_frac",
+				    "ext_i2s", "xin12m" };
+PNAME(mux_edp_24m_p)		= { "dummy", "xin24m" };
+PNAME(mux_vip_out_p)		= { "vip_src", "xin24m" };
+PNAME(mux_usbphy480m_p)		= { "usbotg_out", "xin24m" };
+PNAME(mux_hsic_usbphy480m_p)	= { "usbotg_out", "dummy" };
+PNAME(mux_hsicphy480m_p)	= { "cpll", "gpll", "usbphy_480m" };
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "xin24m" };
+PNAME(mux_uart3_p)		= { "uart3_src", "uart3_frac", "xin24m" };
+PNAME(mux_uart4_p)		= { "uart4_src", "uart4_frac", "xin24m" };
+PNAME(mux_mac_p)		= { "mac_pll_src", "ext_gmac" };
+PNAME(mux_mmc_src_p)		= { "cpll", "gpll", "usbphy_480m", "xin24m" };
+
+static struct rockchip_pll_clock rk3368_pll_clks[] __initdata = {
+	[apllb] = PLL(pll_rk3066, PLL_APLLB, "apllb", mux_pll_p, 0, RK3368_PLL_CON(0),
+		     RK3368_PLL_CON(3), 8, 1, 0, rk3368_pll_rates),
+	[aplll] = PLL(pll_rk3066, PLL_APLLL, "aplll", mux_pll_p, 0, RK3368_PLL_CON(4),
+		     RK3368_PLL_CON(7), 8, 0, 0, rk3368_pll_rates),
+	[dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3368_PLL_CON(8),
+		     RK3368_PLL_CON(11), 8, 2, 0, NULL),
+	[cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3368_PLL_CON(12),
+		     RK3368_PLL_CON(15), 8, 3, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+	[gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3368_PLL_CON(16),
+		     RK3368_PLL_CON(19), 8, 4, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+	[npll] = PLL(pll_rk3066, PLL_NPLL, "npll",  mux_pll_p, 0, RK3368_PLL_CON(20),
+		     RK3368_PLL_CON(23), 8, 5, ROCKCHIP_PLL_SYNC_RATE, rk3368_pll_rates),
+};
+
+static struct clk_div_table div_ddrphy_t[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 3, .div = 4 },
+	{ /* sentinel */ },
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
+	.core_reg = RK3368_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 15,
+};
+
+static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
+	.core_reg = RK3368_CLKSEL_CON(2),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_shift = 7,
+};
+
+#define RK3368_DIV_ACLKM_MASK		0x1f
+#define RK3368_DIV_ACLKM_SHIFT		8
+#define RK3368_DIV_ATCLK_MASK		0x1f
+#define RK3368_DIV_ATCLK_SHIFT		0
+#define RK3368_DIV_PCLK_DBG_MASK	0x1f
+#define RK3368_DIV_PCLK_DBG_SHIFT	8
+
+#define RK3368_CLKSEL0(_offs, _aclkm)					\
+	{								\
+		.reg = RK3288_CLKSEL_CON(0 + _offs),			\
+		.val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK,	\
+				RK3368_DIV_ACLKM_SHIFT),		\
+	}
+#define RK3368_CLKSEL1(_offs, _atclk, _pdbg)				\
+	{								\
+		.reg = RK3288_CLKSEL_CON(1 + _offs),			\
+		.val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK,	\
+				RK3368_DIV_ATCLK_SHIFT) |		\
+		       HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK,	\
+				RK3368_DIV_PCLK_DBG_SHIFT),		\
+	}
+
+/* cluster_b: aclkm in clksel0, rest in clksel1 */
+#define RK3368_CPUCLKB_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3368_CLKSEL0(0, _aclkm),			\
+			RK3368_CLKSEL1(0, _atclk, _pdbg),		\
+		},							\
+	}
+
+/* cluster_l: aclkm in clksel2, rest in clksel3 */
+#define RK3368_CPUCLKL_RATE(_prate, _aclkm, _atclk, _pdbg)		\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK3368_CLKSEL0(2, _aclkm),			\
+			RK3368_CLKSEL1(2, _atclk, _pdbg),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
+	RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
+	RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
+	RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
+	RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
+	RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
+	RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
+	RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
+	RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
+	RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
+	RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
+	RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
+	RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
+	RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
+	RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
+	RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
+	RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
+	RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
+	RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
+	RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
+	RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
+};
+
+static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(13), 8, 1, MFLAGS),
+
+	GATE(0, "apllb_core", "apllb", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 0, GFLAGS),
+	GATE(0, "gpllb_core", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 1, GFLAGS),
+
+	GATE(0, "aplll_core", "aplll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 4, GFLAGS),
+	GATE(0, "gplll_core", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 5, GFLAGS),
+
+	DIV(0, "aclkm_core_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "atclk_core_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "pclk_dbg_b", "armclkb", 0,
+			RK3368_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+	DIV(0, "aclkm_core_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(2), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "atclk_core_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+	DIV(0, "pclk_dbg_l", "armclkl", 0,
+			RK3368_CLKSEL_CON(3), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
+
+	GATE(0, "apllb_cs", "apllb", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 9, GFLAGS),
+	GATE(0, "aplll_cs", "aplll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 10, GFLAGS),
+	GATE(0, "gpll_cs", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(0), 8, GFLAGS),
+	COMPOSITE_NOGATE(0, "sclk_cs_pre", mux_cs_src_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(4), 6, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(0, "clkin_trace", "sclk_cs_pre", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(4), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(0), 13, GFLAGS),
+
+	COMPOSITE(0, "aclk_cci_pre", mux_pll_src_cpll_gpll_usb_npll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(5), 6, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(0), 12, GFLAGS),
+	GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3368_CLKGATE_CON(7), 10, GFLAGS),
+
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", 0,
+			RK3368_CLKGATE_CON(1), 9, GFLAGS),
+	COMPOSITE_NOGATE_DIVTBL(0, "ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(13), 4, 1, MFLAGS, 0, 2, DFLAGS, div_ddrphy_t),
+
+	GATE(0, "sclk_ddr", "ddrphy_div4", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(6), 14, GFLAGS),
+	GATE(0, "sclk_ddr4x", "ddrphy_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(6), 15, GFLAGS),
+
+	GATE(0, "gpll_aclk_bus", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(0, "cpll_aclk_bus", "cpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 11, GFLAGS),
+	COMPOSITE_NOGATE(0, "aclk_bus_src", mux_aclk_bus_src_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 7, 1, MFLAGS, 0, 5, DFLAGS),
+
+	GATE(ACLK_BUS, "aclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(1), 0, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_BUS, "pclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 12, 3, DFLAGS,
+			RK3368_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus", "aclk_bus_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(8), 8, 2, DFLAGS,
+			RK3368_CLKGATE_CON(1), 1, GFLAGS),
+	COMPOSITE_NOMUX(0, "sclk_crypto", "aclk_bus_src", 0,
+			RK3368_CLKSEL_CON(10), 14, 2, DFLAGS,
+			RK3368_CLKGATE_CON(7), 2, GFLAGS),
+
+	COMPOSITE(0, "fclk_mcu_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(1), 3, GFLAGS),
+	/*
+	 * stclk_mcu is listed as child of fclk_mcu_src in diagram 5,
+	 * but stclk_mcu has an additional own divider in diagram 2
+	 */
+	COMPOSITE_NOMUX(0, "stclk_mcu", "fclk_mcu_src", 0,
+			RK3368_CLKSEL_CON(12), 8, 3, DFLAGS,
+			RK3368_CLKGATE_CON(13), 13, GFLAGS),
+
+	COMPOSITE(0, "i2s_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(27), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(6), 1, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_8ch_frac", "i2s_8ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(28), 0,
+			RK3368_CLKGATE_CON(6), 2, GFLAGS),
+	MUX(0, "i2s_8ch_pre", mux_i2s_8ch_pre_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(27), 8, 2, MFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_8CH_OUT, "i2s_8ch_clkout", mux_i2s_8ch_clkout_p, 0,
+			RK3368_CLKSEL_CON(27), 15, 1, MFLAGS,
+			RK3368_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(SCLK_I2S_8CH, "sclk_i2s_8ch", "i2s_8ch_pre", CLK_SET_RATE_PARENT,
+			RK3368_CLKGATE_CON(6), 3, GFLAGS),
+	COMPOSITE(0, "spdif_8ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(31), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(6), 4, GFLAGS),
+	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(32), 0,
+			RK3368_CLKGATE_CON(6), 5, GFLAGS),
+	COMPOSITE_NODIV(SCLK_SPDIF_8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
+			RK3368_CLKSEL_CON(31), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(6), 6, GFLAGS),
+	COMPOSITE(0, "i2s_2ch_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(53), 12, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(5), 13, GFLAGS),
+	COMPOSITE_FRAC(0, "i2s_2ch_frac", "i2s_2ch_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(54), 0,
+			RK3368_CLKGATE_CON(5), 14, GFLAGS),
+	COMPOSITE_NODIV(SCLK_I2S_2CH, "sclk_i2s_2ch", mux_i2s_2ch_p, 0,
+			RK3368_CLKSEL_CON(53), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(5), 15, GFLAGS),
+
+	COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3368_CLKSEL_CON(46), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(6), 12, GFLAGS),
+	GATE(0, "sclk_hsadc_tsp", "ext_hsadc_tsp", 0,
+			RK3368_CLKGATE_CON(13), 7, GFLAGS),
+
+	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(35), 12, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(37), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 4, GFLAGS),
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(37), 8, 1, MFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 3
+	 */
+
+	COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 6, GFLAGS),
+	COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 7, GFLAGS),
+
+	/*
+	 * We introduce a virtual node of hclk_vodec_pre_v to split one clock
+	 * struct with a gate and a fix divider into two node in software.
+	 */
+	GATE(0, "hclk_video_pre_v", "aclk_vdpu", 0,
+		RK3368_CLKGATE_CON(4), 8, GFLAGS),
+
+	COMPOSITE(0, "sclk_hevc_cabac_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+			RK3368_CLKSEL_CON(17), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 1, GFLAGS),
+	COMPOSITE(0, "sclk_hevc_core_src", mux_pll_src_cpll_gpll_npll_usb_p, 0,
+			RK3368_CLKSEL_CON(17), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 2, GFLAGS),
+
+	COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(19), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 0, GFLAGS),
+	DIV(0, "hclk_vio", "aclk_vio0", 0,
+			RK3368_CLKSEL_CON(21), 0, 5, DFLAGS),
+
+	COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(18), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 3, GFLAGS),
+	COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_cpll_gpll_usb_p, 0,
+			RK3368_CLKSEL_CON(18), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 4, GFLAGS),
+
+	COMPOSITE(DCLK_VOP, "dclk_vop", mux_pll_src_cpll_gpll_npll_p, 0,
+			RK3368_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK3368_CLKGATE_CON(4), 1, GFLAGS),
+
+	GATE(SCLK_VOP0_PWM, "sclk_vop0_pwm", "xin24m", 0,
+			RK3368_CLKGATE_CON(4), 2, GFLAGS),
+
+	COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(22), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(4), 9, GFLAGS),
+
+	GATE(0, "pclk_isp_in", "ext_isp", 0,
+			RK3368_CLKGATE_CON(17), 2, GFLAGS),
+	INVERTER(PCLK_ISP, "pclk_isp", "pclk_isp_in",
+			RK3368_CLKSEL_CON(21), 6, IFLAGS),
+
+	GATE(0, "pclk_vip_in", "ext_vip", 0,
+			RK3368_CLKGATE_CON(16), 13, GFLAGS),
+	INVERTER(PCLK_VIP, "pclk_vip", "pclk_vip_in",
+			RK3368_CLKSEL_CON(21), 13, IFLAGS),
+
+	GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
+			RK3368_CLKGATE_CON(4), 13, GFLAGS),
+	GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
+			RK3368_CLKGATE_CON(5), 12, GFLAGS),
+
+	COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
+			RK3368_CLKGATE_CON(4), 5, GFLAGS),
+	COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0,
+			RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS),
+
+	COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0,
+			RK3368_CLKSEL_CON(23), 8, 1, MFLAGS,
+			RK3368_CLKGATE_CON(5), 4, GFLAGS),
+	COMPOSITE(SCLK_EDP, "sclk_edp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(23), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(5), 3, GFLAGS),
+
+	COMPOSITE(SCLK_HDCP, "sclk_hdcp", mux_pll_src_cpll_gpll_npll_npll_p, 0,
+			RK3368_CLKSEL_CON(55), 6, 2, MFLAGS, 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(5), 5, GFLAGS),
+
+	DIV(0, "pclk_pd_alive", "gpll", 0,
+			RK3368_CLKSEL_CON(10), 8, 5, DFLAGS),
+
+	/* sclk_timer has a gate in the sgrf */
+
+	COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(10), 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(7), 9, GFLAGS),
+	GATE(SCLK_PVTM_PMU, "sclk_pvtm_pmu", "xin24m", 0,
+			RK3368_CLKGATE_CON(7), 3, GFLAGS),
+	COMPOSITE(0, "sclk_gpu_core_src", mux_pll_src_cpll_gpll_usb_npll_p, 0,
+			RK3368_CLKSEL_CON(14), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(4), 11, GFLAGS),
+	MUX(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(14), 14, 1, MFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_gpu_mem_pre", "aclk_gpu_src", 0,
+			RK3368_CLKSEL_CON(14), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 8, GFLAGS),
+	COMPOSITE_NOMUX(0, "aclk_gpu_cfg_pre", "aclk_gpu_src", 0,
+			RK3368_CLKSEL_CON(16), 8, 5, DFLAGS,
+			RK3368_CLKGATE_CON(5), 9, GFLAGS),
+	GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0,
+			RK3368_CLKGATE_CON(7), 11, GFLAGS),
+
+	COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(9), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(3), 0, GFLAGS),
+	COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
+			RK3368_CLKSEL_CON(9), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3368_CLKGATE_CON(3), 3, GFLAGS),
+	COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKSEL_CON(9), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK3368_CLKGATE_CON(3), 2, GFLAGS),
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(3), 1, GFLAGS),
+
+	GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3368_CLKGATE_CON(4), 14, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+
+	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(45), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 7, GFLAGS),
+	COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(45), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(46), 15, 1, MFLAGS, 8, 7, DFLAGS,
+			RK3368_CLKGATE_CON(3), 9, GFLAGS),
+
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(50), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 12, GFLAGS),
+	COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(48), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 13, GFLAGS),
+	COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
+			RK3368_CLKSEL_CON(51), 8, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(7), 15, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK3368_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3368_SDMMC_CON1, 0),
+
+	MMC(SCLK_SDIO0_DRV,    "sdio0_drv",    "sclk_sdio0", RK3368_SDIO0_CON0, 1),
+	MMC(SCLK_SDIO0_SAMPLE, "sdio0_sample", "sclk_sdio0", RK3368_SDIO0_CON1, 0),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK3368_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK3368_EMMC_CON1,  0),
+
+	GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin24m", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(8), 1, GFLAGS),
+
+	/* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+	GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", CLK_IGNORE_UNUSED,
+			RK3368_CLKGATE_CON(8), 4, GFLAGS),
+
+	/* pmu_grf_soc_con0[6] allows to select between xin32k and pvtm_pmu */
+	COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0,
+			RK3368_CLKSEL_CON(25), 0, 6, DFLAGS,
+			RK3368_CLKGATE_CON(3), 5, GFLAGS),
+
+	COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0,
+			RK3368_CLKSEL_CON(25), 8, 8, DFLAGS,
+			RK3368_CLKGATE_CON(3), 6, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(47), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(7), 8, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(52), 7, 1, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(6), 7, GFLAGS),
+
+	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb_usb_p, 0,
+			RK3368_CLKSEL_CON(33), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(34), 0,
+			RK3368_CLKGATE_CON(2), 1, GFLAGS),
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(33), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(35), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 2, GFLAGS),
+	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(36), 0,
+			RK3368_CLKGATE_CON(2), 3, GFLAGS),
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(35), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(39), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 6, GFLAGS),
+	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(40), 0,
+			RK3368_CLKGATE_CON(2), 7, GFLAGS),
+	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(39), 8, 2, MFLAGS),
+
+	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
+			RK3368_CLKSEL_CON(41), 0, 7, DFLAGS,
+			RK3368_CLKGATE_CON(2), 8, GFLAGS),
+	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(42), 0,
+			RK3368_CLKGATE_CON(2), 9, GFLAGS),
+	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(41), 8, 2, MFLAGS),
+
+	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
+			RK3368_CLKSEL_CON(43), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK3368_CLKGATE_CON(3), 4, GFLAGS),
+	MUX(SCLK_MAC, "mac_clk", mux_mac_p, CLK_SET_RATE_PARENT,
+			RK3368_CLKSEL_CON(43), 8, 1, MFLAGS),
+	GATE(SCLK_MACREF_OUT, "sclk_macref_out", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 7, GFLAGS),
+	GATE(SCLK_MACREF, "sclk_macref", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(SCLK_MAC_RX, "sclk_mac_rx", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 4, GFLAGS),
+	GATE(SCLK_MAC_TX, "sclk_mac_tx", "mac_clk", 0,
+			RK3368_CLKGATE_CON(7), 5, GFLAGS),
+
+	GATE(0, "jtag", "ext_jtag", 0,
+			RK3368_CLKGATE_CON(7), 0, GFLAGS),
+
+	COMPOSITE_NODIV(0, "hsic_usbphy_480m", mux_hsic_usbphy480m_p, 0,
+			RK3368_CLKSEL_CON(26), 8, 2, MFLAGS,
+			RK3368_CLKGATE_CON(8), 0, GFLAGS),
+	COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0,
+			RK3368_CLKSEL_CON(26), 12, 2, MFLAGS,
+			RK3368_CLKGATE_CON(8), 7, GFLAGS),
+	GATE(SCLK_HSICPHY12M, "sclk_hsicphy12m", "xin12m", 0,
+			RK3368_CLKGATE_CON(8), 6, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 5
+	 */
+
+	/* aclk_cci_pre gates */
+	GATE(0, "aclk_core_niu_cpup", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 4, GFLAGS),
+	GATE(0, "aclk_core_niu_cci", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 3, GFLAGS),
+	GATE(0, "aclk_cci400", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 2, GFLAGS),
+	GATE(0, "aclk_adb400m_pd_core_b", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 1, GFLAGS),
+	GATE(0, "aclk_adb400m_pd_core_l", "aclk_cci_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 0, GFLAGS),
+
+	/* aclkm_core_* gates */
+	GATE(0, "aclk_adb400s_pd_core_b", "aclkm_core_b", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(0, "aclk_adb400s_pd_core_l", "aclkm_core_l", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 0, GFLAGS),
+
+	/* armclk* gates */
+	GATE(0, "sclk_dbg_pd_core_b", "armclkb", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(0, "sclk_dbg_pd_core_l", "armclkl", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(9), 1, GFLAGS),
+
+	/* sclk_cs_pre gates */
+	GATE(0, "sclk_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 7, GFLAGS),
+	GATE(0, "pclk_core_niu_sdbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 6, GFLAGS),
+	GATE(0, "hclk_core_niu_dbg", "sclk_cs_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(11), 5, GFLAGS),
+
+	/* aclk_bus gates */
+	GATE(0, "aclk_strc_sys", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 12, GFLAGS),
+	GATE(ACLK_DMAC_BUS, "aclk_dmac_bus", "aclk_bus", 0, RK3368_CLKGATE_CON(12), 11, GFLAGS),
+	GATE(0, "sclk_intmem1", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 6, GFLAGS),
+	GATE(0, "sclk_intmem0", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 5, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 4, GFLAGS),
+	GATE(0, "aclk_gic400", "aclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 9, GFLAGS),
+
+	/* sclk_ddr gates */
+	GATE(0, "nclk_ddrupctl", "sclk_ddr", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(13), 2, GFLAGS),
+
+	/* clk_hsadc_tsp is part of diagram2 */
+
+	/* fclk_mcu_src gates */
+	GATE(0, "hclk_noc_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 14, GFLAGS),
+	GATE(0, "fclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 12, GFLAGS),
+	GATE(0, "hclk_mcu", "fclk_mcu_src", 0, RK3368_CLKGATE_CON(13), 11, GFLAGS),
+
+	/* hclk_cpu gates */
+	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 10, GFLAGS),
+	GATE(HCLK_ROM, "hclk_rom", "hclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 9, GFLAGS),
+	GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 8, GFLAGS),
+	GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_bus", 0, RK3368_CLKGATE_CON(12), 7, GFLAGS),
+	GATE(HCLK_TSP, "hclk_tsp", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 10, GFLAGS),
+	GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 4, GFLAGS),
+	GATE(MCLK_CRYPTO, "mclk_crypto", "hclk_bus", 0, RK3368_CLKGATE_CON(13), 3, GFLAGS),
+
+	/* pclk_cpu gates */
+	GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 14, GFLAGS),
+	GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 13, GFLAGS),
+	GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 3, GFLAGS),
+	GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 2, GFLAGS),
+	GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 0, RK3368_CLKGATE_CON(12), 1, GFLAGS),
+	GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(12), 0, GFLAGS),
+	GATE(PCLK_SIM, "pclk_sim", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 8, GFLAGS),
+	GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 5, GFLAGS),
+	GATE(0, "pclk_efuse_256", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(0, "pclk_efuse_1024", "pclk_bus", 0, RK3368_CLKGATE_CON(13), 0, GFLAGS),
+
+	/*
+	 * video clk gates
+	 * aclk_video(_pre) can actually select between parents of aclk_vdpu
+	 * and aclk_vepu by setting bit GRF_SOC_CON0[7].
+	 */
+	GATE(ACLK_VIDEO, "aclk_video", "aclk_vdpu", 0, RK3368_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(SCLK_HEVC_CABAC, "sclk_hevc_cabac", "sclk_hevc_cabac_src", 0, RK3368_CLKGATE_CON(15), 3, GFLAGS),
+	GATE(SCLK_HEVC_CORE, "sclk_hevc_core", "sclk_hevc_core_src", 0, RK3368_CLKGATE_CON(15), 2, GFLAGS),
+	GATE(HCLK_VIDEO, "hclk_video", "hclk_video_pre", 0, RK3368_CLKGATE_CON(15), 1, GFLAGS),
+
+	/* aclk_rga_pre gates */
+	GATE(ACLK_VIO1_NOC, "aclk_vio1_noc", "aclk_rga_pre", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 10, GFLAGS),
+	GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(16), 0, GFLAGS),
+	GATE(ACLK_HDCP, "aclk_hdcp", "aclk_rga_pre", 0, RK3368_CLKGATE_CON(17), 10, GFLAGS),
+
+	/* aclk_vio0 gates */
+	GATE(ACLK_VIP, "aclk_vip", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 11, GFLAGS),
+	GATE(ACLK_VIO0_NOC, "aclk_vio0_noc", "aclk_vio0", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 9, GFLAGS),
+	GATE(ACLK_VOP, "aclk_vop", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 5, GFLAGS),
+	GATE(ACLK_VOP_IEP, "aclk_vop_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 4, GFLAGS),
+	GATE(ACLK_IEP, "aclk_iep", "aclk_vio0", 0, RK3368_CLKGATE_CON(16), 2, GFLAGS),
+
+	/* sclk_isp gates */
+	GATE(HCLK_ISP, "hclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(16), 14, GFLAGS),
+	GATE(ACLK_ISP, "aclk_isp", "sclk_isp", 0, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+
+	/* hclk_vio gates */
+	GATE(HCLK_VIP, "hclk_vip", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 12, GFLAGS),
+	GATE(HCLK_VIO_NOC, "hclk_vio_noc", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 8, GFLAGS),
+	GATE(HCLK_VIO_AHB_ARBI, "hclk_vio_ahb_arbi", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(16), 7, GFLAGS),
+	GATE(HCLK_VOP, "hclk_vop", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 6, GFLAGS),
+	GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 3, GFLAGS),
+	GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3368_CLKGATE_CON(16), 1, GFLAGS),
+	GATE(HCLK_VIO_HDCPMMU, "hclk_hdcpmmu", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 12, GFLAGS),
+	GATE(HCLK_VIO_H2P, "hclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 7, GFLAGS),
+
+	/*
+	 * pclk_vio gates
+	 * pclk_vio comes from the exactly same source as hclk_vio
+	 */
+	GATE(PCLK_HDCP, "pclk_hdcp", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 11, GFLAGS),
+	GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 9, GFLAGS),
+	GATE(PCLK_VIO_H2P, "pclk_vio_h2p", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 8, GFLAGS),
+	GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 6, GFLAGS),
+	GATE(PCLK_MIPI_CSI, "pclk_mipi_csi", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+	GATE(PCLK_MIPI_DSI0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+
+	/* ext_vip gates in diagram3 */
+
+	/* gpu gates */
+	GATE(SCLK_GPU_CORE, "sclk_gpu_core", "sclk_gpu_core_src", 0, RK3368_CLKGATE_CON(18), 2, GFLAGS),
+	GATE(ACLK_GPU_MEM, "aclk_gpu_mem", "aclk_gpu_mem_pre", 0, RK3368_CLKGATE_CON(18), 1, GFLAGS),
+	GATE(ACLK_GPU_CFG, "aclk_gpu_cfg", "aclk_gpu_cfg_pre", 0, RK3368_CLKGATE_CON(18), 0, GFLAGS),
+
+	/* aclk_peri gates */
+	GATE(ACLK_DMAC_PERI, "aclk_dmac_peri", "aclk_peri", 0, RK3368_CLKGATE_CON(19), 3, GFLAGS),
+	GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 2, GFLAGS),
+	GATE(HCLK_SFC, "hclk_sfc", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 15, GFLAGS),
+	GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3368_CLKGATE_CON(20), 13, GFLAGS),
+	GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 8, GFLAGS),
+	GATE(ACLK_PERI_MMU, "aclk_peri_mmu", "aclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(21), 4, GFLAGS),
+
+	/* hclk_peri gates */
+	GATE(0, "hclk_peri_axi_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 0, GFLAGS),
+	GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 11, GFLAGS),
+	GATE(0, "hclk_mmc_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 10, GFLAGS),
+	GATE(0, "hclk_emem_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 9, GFLAGS),
+	GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 7, GFLAGS),
+	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 6, GFLAGS),
+	GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 5, GFLAGS),
+	GATE(HCLK_HOST1, "hclk_host1", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 4, GFLAGS),
+	GATE(HCLK_HOST0, "hclk_host0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 3, GFLAGS),
+	GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3368_CLKGATE_CON(20), 2, GFLAGS),
+	GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(20), 1, GFLAGS),
+	GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 3, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 2, GFLAGS),
+	GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 1, GFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3368_CLKGATE_CON(21), 0, GFLAGS),
+
+	/* pclk_peri gates */
+	GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 15, GFLAGS),
+	GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 14, GFLAGS),
+	GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 13, GFLAGS),
+	GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 12, GFLAGS),
+	GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 11, GFLAGS),
+	GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 10, GFLAGS),
+	GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 9, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 8, GFLAGS),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 7, GFLAGS),
+	GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 6, GFLAGS),
+	GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 5, GFLAGS),
+	GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3368_CLKGATE_CON(19), 4, GFLAGS),
+	GATE(0, "pclk_peri_axi_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(19), 1, GFLAGS),
+	GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 14, GFLAGS),
+	GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3368_CLKGATE_CON(20), 0, GFLAGS),
+
+	/* pclk_pd_alive gates */
+	GATE(PCLK_TIMER1, "pclk_timer1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(PCLK_TIMER0, "pclk_timer0", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 7, GFLAGS),
+	GATE(0, "pclk_alive_niu", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 12, GFLAGS),
+	GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 11, GFLAGS),
+	GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 3, GFLAGS),
+	GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 2, GFLAGS),
+	GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3368_CLKGATE_CON(14), 1, GFLAGS),
+
+	/*
+	 * pclk_vio gates
+	 * pclk_vio comes from the exactly same source as hclk_vio
+	 */
+	GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+	GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS),
+
+	/* pclk_pd_pmu gates */
+	GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 0, GFLAGS),
+	GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3368_CLKGATE_CON(17), 4, GFLAGS),
+	GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 3, GFLAGS),
+	GATE(0, "pclk_pmu_noc", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+	GATE(0, "pclk_intmem1", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 1, GFLAGS),
+	GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(17), 2, GFLAGS),
+
+	/* timer gates */
+	GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
+	GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
+	GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
+	GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
+	GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
+	GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
+	GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
+	GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
+	GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
+	GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
+	GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
+	GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
+};
+
+static void __init rk3368_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+	struct clk *clk;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	/* xin12m is created by an cru-internal divider */
+	clk = clk_register_fixed_factor(NULL, "ddrphy_div4", "ddrphy_src", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock xin12m: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	clk = clk_register_fixed_factor(NULL, "hclk_video_pre",
+					"hclk_video_pre_v", 0, 1, 4);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
+			__func__, PTR_ERR(clk));
+
+	/* Watchdog pclk is controlled by sgrf_soc_con3[7]. */
+	clk = clk_register_fixed_factor(NULL, "pclk_wdt", "pclk_pd_alive", 0, 1, 1);
+	if (IS_ERR(clk))
+		pr_warn("%s: could not register clock pclk_wdt: %ld\n",
+			__func__, PTR_ERR(clk));
+	else
+		rockchip_clk_add_lookup(clk, PCLK_WDT);
+
+	rockchip_clk_register_plls(rk3368_pll_clks,
+				   ARRAY_SIZE(rk3368_pll_clks),
+				   RK3368_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(rk3368_clk_branches,
+				  ARRAY_SIZE(rk3368_clk_branches));
+
+	rockchip_clk_register_armclk(ARMCLKB, "armclkb",
+			mux_armclkb_p, ARRAY_SIZE(mux_armclkb_p),
+			&rk3368_cpuclkb_data, rk3368_cpuclkb_rates,
+			ARRAY_SIZE(rk3368_cpuclkb_rates));
+
+	rockchip_clk_register_armclk(ARMCLKL, "armclkl",
+			mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+			&rk3368_cpuclkl_data, rk3368_cpuclkl_rates,
+			ARRAY_SIZE(rk3368_cpuclkl_rates));
+
+	rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
+}
+CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index b72dad0..f506df8 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -57,6 +57,22 @@
 #define RK3288_EMMC_CON0		0x218
 #define RK3288_EMMC_CON1		0x21c
 
+#define RK3368_PLL_CON(x)		RK2928_PLL_CON(x)
+#define RK3368_CLKSEL_CON(x)		((x) * 0x4 + 0x100)
+#define RK3368_CLKGATE_CON(x)		((x) * 0x4 + 0x200)
+#define RK3368_GLB_SRST_FST		0x280
+#define RK3368_GLB_SRST_SND		0x284
+#define RK3368_SOFTRST_CON(x)		((x) * 0x4 + 0x300)
+#define RK3368_MISC_CON			0x380
+#define RK3368_SDMMC_CON0		0x400
+#define RK3368_SDMMC_CON1		0x404
+#define RK3368_SDIO0_CON0		0x408
+#define RK3368_SDIO0_CON1		0x40c
+#define RK3368_SDIO1_CON0		0x410
+#define RK3368_SDIO1_CON1		0x414
+#define RK3368_EMMC_CON0		0x418
+#define RK3368_EMMC_CON1		0x41c
+
 enum rockchip_pll_type {
 	pll_rk3066,
 };
-- 
2.1.4



From mark.yao at rock-chips.com  Thu Jun 18 19:50:54 2015
From: mark.yao at rock-chips.com (Mark yao)
Date: Fri, 19 Jun 2015 10:50:54 +0800
Subject: [PATCH 1/6] drm/rockchip: import dma_buf to gem
In-Reply-To: <20150618105715.GJ7557@n2100.arm.linux.org.uk>
References: <1434613770-6608-1-git-send-email-mark.yao@rock-chips.com>
 <1434613770-6608-2-git-send-email-mark.yao@rock-chips.com>
 <20150618105715.GJ7557@n2100.arm.linux.org.uk>
Message-ID: <5583838E.7080001@rock-chips.com>

Thanks Russell
On 2015?06?18? 18:57, Russell King - ARM Linux wrote:
> This is wrong.
>
> First, if you can only cope with a single scatterlist entry, you need to
> enforce that.  You can do that in your gem_prime_import_sg_table() method
> by checking sgt->nents.
I'm confuse that how to get coherent iova address from nocoherent 
scatterlist with iommu.
I saw the arm_iommu_map_sg, it says that:
         The scatter gather list elements are merged together (if 
possible) and
          tagged with the appropriate dma address and length.

I guess the map_sg maybe merge scatterlist into coherent iova address, 
but I don't know how to
check the "if possible", and the sgt->nents not be 1 when already map to 
coherent iova address.

checking sgt-nents = 1 can sure that iova is coherent, but when coherent 
iova address from
nocoherent scatterlist, I think sgt->nents maybe greater than 1, is 
there a method can deal it?

All above is my guess, maybe wrong, I only tested it with CMA buffer import.

> Secondly, you're mapping an already mapped scatterlist - scatterlists
> are mapped by the exporter inside dma_buf_map_attachment() for your
> device.

Right, found the dma_map_sg on dma_buf_map_attachment().

>
> Thirdly, I hate drm_gem_prime_import() being used on ARM... it forces
> drivers to do something very buggy: the DMA buffer is mapped for DMA
> when the buffer is imported.  If the buffer is a write-combine or cached
> buffer, writes to the buffer after the import will not become visible to
> the display hardware until sometime later (when they're evicted from the
> caches and/or pushed out of the bus structure.)  The DMA mapping should
> be performed as close to the start of DMA as possible.  However, this is
> a long-standing issue I have with dma_buf itself and is not something you
> should be too concerned with in your patch.  Just bear it in mind if you
> start to see corruption of imported buffers - the answer is not more
> dma_map_sg() calls, but to get dma_buf fixed.
Yeah, Got it.

-- 
?ark Yao




From heiko at sntech.de  Fri Jun 19 07:31:14 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Fri, 19 Jun 2015 16:31:14 +0200
Subject: [PATCH] ARM: dts: rockchip: fix rk3288 watchdog irq
Message-ID: <1961157.dsytR1KvKa@phil>

The watchdog irq is actually SPI 79, which translates to the original
111 in the manual where the SPI irqs start at 32.
The current dw_wdt driver does not use the irq at all, so this issue
never surfaced. Nevertheless fix this for a time we want to use the irq.

Fixes: 2ab557b72d46 ("ARM: dts: rockchip: add core rk3288 dtsi")
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
Found while verifying the data for the quite similar rk3368 arm64 soc.

 arch/arm/boot/dts/rk3288.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 22316d0..858efd0 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -626,7 +626,7 @@
 		compatible = "rockchip,rk3288-wdt", "snps,dw-wdt";
 		reg = <0xff800000 0x100>;
 		clocks = <&cru PCLK_WDT>;
-		interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
 		status = "disabled";
 	};
 
-- 
2.1.4




From dianders at chromium.org  Fri Jun 19 08:24:21 2015
From: dianders at chromium.org (Doug Anderson)
Date: Fri, 19 Jun 2015 08:24:21 -0700
Subject: [PATCH] ARM: dts: rockchip: fix rk3288 watchdog irq
In-Reply-To: <1961157.dsytR1KvKa@phil>
References: <1961157.dsytR1KvKa@phil>
Message-ID: <CAD=FV=U3AQY1y6PJP4uBzqBgBkX3GdKtN7iLjGv62w4eZ3W2bQ@mail.gmail.com>

Heiko,

On Fri, Jun 19, 2015 at 7:31 AM, Heiko Stuebner <heiko at sntech.de> wrote:
> The watchdog irq is actually SPI 79, which translates to the original
> 111 in the manual where the SPI irqs start at 32.
> The current dw_wdt driver does not use the irq at all, so this issue
> never surfaced. Nevertheless fix this for a time we want to use the irq.
>
> Fixes: 2ab557b72d46 ("ARM: dts: rockchip: add core rk3288 dtsi")
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>
> ---
> Found while verifying the data for the quite similar rk3368 arm64 soc.
>
>  arch/arm/boot/dts/rk3288.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

* gpio0 shows up in TRM as 113
* gpio0 is in dts as SPI 81
* wdt shows up in TRM as 111
* so wdt should be in dts as SPI 79

...so yup.

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From ykk at rock-chips.com  Fri Jun 19 09:13:37 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:13:37 +0800
Subject: [PATCH v5 0/6] Add dw_hdmi i2s audio support
Message-ID: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>

As Russell have send an series patches for dw_hdmi audio, and most important
it works well on rockchip platform. Cause some patches have been achieve in
Russell's series, so I abondon some patches in this verison.

Here are the abondon patches that already be achieved:
* drm: bridge/dw_hdmi: adjust n/cts setting order
* drm: bridge/dw_hdmi: set ncts_atomic_write & cts_manual
* drm: bridge/dw_hdmi: combine hdmi_set_clock_regenerator_n() and hdmi_regenerate_cts()
* drm: bridge/dw_hdmi: add enable/disable to dw_hdmi_audio callbacks

And I also abondon some interrupt patches that is not a common bug in dw_hdmi
driver, but is a rockchip platform bug which HDMI registers would reset by CRU
module after system suspend/resume (in this case HPD interrupt mask would reset,
then driver can't respond hot plug event after system resume).

Here are the abondon patches that used to "fix" dw_hdmi interrupt bug:
* drm: bridge/dw_hdmi: add irq control to suspend/resume
* drm: bridge/dw_hdmi: wrap irq control in fucntions
* drm: rockchip/dw_hdmi_rockchip: add resume/suspend support

Here are the leave list that I have make in my series:
- add n/cts combinations for more display modes
- enable audio support when sink device is HDMI monitor and has audio
- rename dw_hdmi-ahb-audio.h to dw_hdmi-audio.h
- add dw_hdmi i2s audio driver
- add rockchip_hdmi_audio sound card driver
- add dt-bindings for documentation for rockchip_hdmi_audio driver


Changes in v5:
- make more words in commit message.
- Take Russell suggest that create "sink_has_audio" and "sink_is_hdmi" in
  struct hdmi, and keep vmode's mdvi changeless.
- Config fc_invidconf to HDMI mode when sink device is HDMI monitor.
- Take Mark Brown suggest that remove jack_status recorded, report
  jack status directly when hdmi plug happend, and remove devm_kfree
  and devm_free_irq.
- Correct the MODULE_LICENSE to "GPL v2"
- Move source from sound/soc/codecs to drivers/gpu/drm/bridge/
- Rename dai driver name to "dw-hdmi-i2s-hifi"
- Take Mark Brown suggest that remove the no useful code in probe func,
  and remove the snd_soc_dai_set_fmt() snd_soc_unregister_card(), remove
  those noisy dev_info()
- Rename codec_dai_name to "dw-hdmi-i2s-hifi"

Changes in v4:
- Take Dainel suggest that introduce drm_detect_monitor_audio() to judge
  whether source should config audio.
- Replace delaywork with irq thread, and add suspend/resume interfaces,
  replace "dw-hdmi-audio" with consecutive strings.
- Add ".pm = &snd_soc_pm_ops,"

Changes in v3:
- Keep audio format config function in dw-hdmi-audio driver
  and remove audio_config & get_connect_status functions,
  move jack control to dw-hdmi-audio completely.
- Delete the operation of jack in rockchip-hdmi-audio driver,
  get ready to switch to simple-audio-card driver.
- modify cpu-of-node to i2s-controller

Changes in v2:
- Update dw_hdmi audio control interfaces, and adjust jack report process
- give "codec-name" & "codec-dai-name" an const name
- remove codec-name and codec-dai-name
- rename rockchip,rockchip-hdmi-audio.txt to rockchip,rockchip-dw-hdmi-audio.txt

Yakir Yang (6):
  drm: bridge/dw_hdmi: add audio support for more display resolutions
  drm: bridge/dw_hdmi: enable audio when sink device is HDMI and has audio
  drm: bridge/dw_hdmi: rename dw_hdmi-ahb-audio.h to dw_hdmi-audio.h
  drm: bridge/dw_hdmi-i2s-audio: add audio driver
  ASoC: rockchip/rockchip-hdmi-audio: add sound driver for hdmi audio
  dt-bindings: Add documentation for rockchip_hdmi_audio driver

 .../sound/rockchip,rockchip-dw-hdmi-audio.txt      |  12 +
 drivers/gpu/drm/bridge/Kconfig                     |   9 +
 drivers/gpu/drm/bridge/Makefile                    |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c         |   2 +-
 .../{dw_hdmi-ahb-audio.h => dw_hdmi-audio.h}       |   0
 drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c         | 398 +++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi.c                   | 100 +++++-
 drivers/gpu/drm/bridge/dw_hdmi.h                   |   3 +
 sound/soc/rockchip/Kconfig                         |   9 +
 sound/soc/rockchip/Makefile                        |   2 +
 sound/soc/rockchip/rockchip_hdmi_audio.c           | 138 +++++++
 11 files changed, 658 insertions(+), 16 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
 rename drivers/gpu/drm/bridge/{dw_hdmi-ahb-audio.h => dw_hdmi-audio.h} (100%)
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c
 create mode 100644 sound/soc/rockchip/rockchip_hdmi_audio.c

-- 
2.1.2




From ykk at rock-chips.com  Fri Jun 19 09:19:12 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:19:12 +0800
Subject: [PATCH v5 1/6] drm: bridge/dw_hdmi: add audio support for more
 display resolutions
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434730752-10829-1-git-send-email-ykk@rock-chips.com>

Just like HDMISpecification 1.4 document descripted, the soure shall
determine the fractional relationship between the TMDS clock an an
audio reference clock, the sink may then recreate the audio clock from
the TMDS clock by using an clock divider. So if we can make sink generate
the correct samplerate, then we can say those display resolutions with
this pixelclock could support audio play.

The exact relationship between the two clocks will be:
	128 * SampleRate = TmdsClock * N / CTS.
So this patch would generate the correct N/CTS values, add audio support
for the below  tmds clocks:
25.175MHz, 40MHz, 54MHz, 65MHz, 74.25MHz, 83.5MHz, 106.5MHz, 108Mhz

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5:
- make more words in commit message.

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 56 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index dc0aed1..f717a2a 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -222,8 +222,24 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
 	case 44100:
 		if (pixel_clk == 25170000)
 			n = 7007;
+		else if (pixel_clk == 25175000)
+			n = 28224;
+		else if (pixel_clk == 40000000)
+			n = 7056;
+		else if (pixel_clk == 54000000)
+			n = 6272;
+		else if (pixel_clk == 65000000)
+			n = 7056;
 		else if (pixel_clk == 74170000)
 			n = 17836;
+		else if (pixel_clk == 74250000)
+			n = 6272;
+		else if (pixel_clk == 83500000)
+			n = 7056;
+		else if (pixel_clk == 106500000)
+			n = 4074;
+		else if (pixel_clk == 108000000)
+			n = 4018;
 		else if (pixel_clk == 148350000)
 			n = (ratio == 150) ? 17836 : 8918;
 		else
@@ -233,10 +249,26 @@ static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
 	case 48000:
 		if (pixel_clk == 25170000)
 			n = (ratio == 150) ? 9152 : 6864;
+		else if (pixel_clk == 25175000)
+			n = 6144;
 		else if (pixel_clk == 27020000)
 			n = (ratio == 150) ? 8192 : 6144;
+		else if (pixel_clk == 40000000)
+			n = 6144;
+		else if (pixel_clk == 54000000)
+			n = 6144;
+		else if (pixel_clk == 65000000)
+			n = 6144;
 		else if (pixel_clk == 74170000)
 			n = 11648;
+		else if (pixel_clk == 74250000)
+			n = 6144;
+		else if (pixel_clk == 83500000)
+			n = 6144;
+		else if (pixel_clk == 106500000)
+			n = 6144;
+		else if (pixel_clk == 108000000)
+			n = 6144;
 		else if (pixel_clk == 148350000)
 			n = (ratio == 150) ? 11648 : 5824;
 		else
@@ -284,10 +316,16 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 	case 96000:
 	case 192000:
 		switch (pixel_clk) {
+		case 25175000:
 		case 25200000:
 		case 27000000:
+		case 40000000:
 		case 54000000:
+		case 65000000:
 		case 74250000:
+		case 83500000:
+		case 106500000:
+		case 108000000:
 		case 148500000:
 			cts = pixel_clk / 1000;
 			break;
@@ -308,18 +346,36 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
 	case 88200:
 	case 176400:
 		switch (pixel_clk) {
+		case 25175000:
+			cts = 125875;
+			break;
 		case 25200000:
 			cts = 28000;
 			break;
 		case 27000000:
 			cts = 30000;
 			break;
+		case 40000000:
+			cts = 50000;
+			break;
 		case 54000000:
 			cts = 60000;
 			break;
+		case 65000000:
+			cts = 81250;
+			break;
 		case 74250000:
 			cts = 82500;
 			break;
+		case 83500000:
+			cts = 104375;
+			break;
+		case 106500000:
+			cts = 88750;
+			break;
+		case 108000000:
+			cts = 76875;
+			break;
 		case 148500000:
 			cts = 165000;
 			break;
-- 
2.1.2




From ykk at rock-chips.com  Fri Jun 19 09:21:42 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:21:42 +0800
Subject: [PATCH v5 2/6] drm: bridge/dw_hdmi: enable audio when sink device is
 HDMI and has audio
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434730902-10875-1-git-send-email-ykk@rock-chips.com>

The original code only provide audio func when video code is a CEA mode,
but I found that No-CEA mode could also play sound when sink is HDMI mode
and has audio. So I think if sink device has the ability to play audio,
then source should enable audio support that set fc_invidconf to HDMI mode
and config n/cts rightly.

And actually we could know those information through parsing sink edid.
drm_detect_hdmi_monitor() could report whether sink is a HDMI monitor,
drm_detect_monitor_audio() could return whether sink has audio.

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5:
- Take Russell suggest that create "sink_has_audio" and "sink_is_hdmi" in
  struct hdmi, and keep vmode's mdvi changeless.
- Config fc_invidconf to HDMI mode when sink device is HDMI monitor.

Changes in v4:
- Take Dainel suggest that introduce drm_detect_monitor_audio() to judge
  whether source should config audio.

Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index f717a2a..417cc82 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -119,6 +119,8 @@ struct dw_hdmi {
 
 	u8 edid[HDMI_EDID_LEN];
 	bool cable_plugin;
+	bool sink_is_hdmi;
+	bool sink_has_audio;
 
 	bool phy_enabled;
 	struct drm_display_mode previous_mode;
@@ -1152,7 +1154,11 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
 		HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
 		HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
 
-	inv_val |= (vmode->mdvi ?
+	/*
+	 * when sink device is hdmi monitor, then we can config
+	 * this to hdmi_mode even if the video mode is No-CEA mode.
+	 */
+	inv_val |= (hdmi->sink_is_hdmi ?
 		HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE :
 		HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE);
 
@@ -1330,11 +1336,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
 	/* HDMI Initialization Step B.3 */
 	dw_hdmi_enable_video_path(hdmi);
 
-	/* not for DVI mode */
-	if (hdmi->hdmi_data.video_mode.mdvi) {
-		dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
+	if (!hdmi->sink_has_audio) {
+		dev_info(hdmi->dev, "sink device does not support audio\n");
 	} else {
-		dev_dbg(hdmi->dev, "%s CEA mode\n", __func__);
+		dev_dbg(hdmi->dev, "sink device support audio\n");
 
 		/* HDMI Initialization Step E - Configure audio */
 		hdmi_clk_regenerator_update_pixel_clock(hdmi);
@@ -1500,6 +1505,9 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
 		dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
 			edid->width_cm, edid->height_cm);
 
+		hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
+		hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
+
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
 		/* Store the ELD */
-- 
2.1.2




From ykk at rock-chips.com  Fri Jun 19 09:24:20 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:24:20 +0800
Subject: [PATCH v5 3/6] drm: bridge/dw_hdmi: rename dw_hdmi-ahb-audio.h to
 dw_hdmi-audio.h
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434731060-10929-1-git-send-email-ykk@rock-chips.com>

First step to make ahb audio driver and i2s audio driver code exist,
share the audio data struct in dw_hdmi-audio.h

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5: None
Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c                      | 2 +-
 drivers/gpu/drm/bridge/{dw_hdmi-ahb-audio.h => dw_hdmi-audio.h} | 0
 drivers/gpu/drm/bridge/dw_hdmi.c                                | 2 +-
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename drivers/gpu/drm/bridge/{dw_hdmi-ahb-audio.h => dw_hdmi-audio.h} (100%)

diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
index 2bb68bd..0a270ea 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.c
@@ -21,7 +21,7 @@
 #include <sound/pcm_drm_eld.h>
 #include <sound/pcm_iec958.h>
 
-#include "dw_hdmi-ahb-audio.h"
+#include "dw_hdmi-audio.h"
 
 #define DRIVER_NAME "dw-hdmi-ahb-audio"
 
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h b/drivers/gpu/drm/bridge/dw_hdmi-audio.h
similarity index 100%
rename from drivers/gpu/drm/bridge/dw_hdmi-ahb-audio.h
rename to drivers/gpu/drm/bridge/dw_hdmi-audio.h
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 417cc82..cbb55ae 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -28,7 +28,7 @@
 #include <drm/bridge/dw_hdmi.h>
 
 #include "dw_hdmi.h"
-#include "dw_hdmi-ahb-audio.h"
+#include "dw_hdmi-audio.h"
 
 #define HDMI_EDID_LEN		512
 
-- 
2.1.2




From ykk at rock-chips.com  Fri Jun 19 09:28:15 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:28:15 +0800
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434731295-11060-1-git-send-email-ykk@rock-chips.com>

Add ALSA based HDMI I2S audio driver for dw_hdmi. Sound card
driver could connect to this codec through the codec dai name
"dw-hdmi-i2s-audio".

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5:
- Take Mark Brown suggest that remove jack_status recorded, report
  jack status directly when hdmi plug happend, and remove devm_kfree
  and devm_free_irq.
- Correct the MODULE_LICENSE to "GPL v2"
- Move source from sound/soc/codecs to drivers/gpu/drm/bridge/
- Rename dai driver name to "dw-hdmi-i2s-hifi"

Changes in v4:
- Replace delaywork with irq thread, and add suspend/resume interfaces,
  replace "dw-hdmi-audio" with consecutive strings.

Changes in v3:
- Keep audio format config function in dw-hdmi-audio driver
  and remove audio_config & get_connect_status functions,
  move jack control to dw-hdmi-audio completely.

Changes in v2:
- Update dw_hdmi audio control interfaces, and adjust jack report process

 drivers/gpu/drm/bridge/Kconfig             |   9 +
 drivers/gpu/drm/bridge/Makefile            |   1 +
 drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c | 398 +++++++++++++++++++++++++++++
 drivers/gpu/drm/bridge/dw_hdmi.c           |  24 +-
 drivers/gpu/drm/bridge/dw_hdmi.h           |   3 +
 5 files changed, 426 insertions(+), 9 deletions(-)
 create mode 100644 drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 204861b..59e3f24 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -14,6 +14,15 @@ config DRM_DW_HDMI_AHB_AUDIO
 	  Designware HDMI block.  This is used in conjunction with
 	  the i.MX6 HDMI driver.
 
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsis Designware I2S Audio interface"
+	depends on DRM_DW_HDMI && SND
+	select SND_PCM
+	help
+	  Support the I2S Audio interface which is part of the Synopsis
+	  Designware HDMI block.  This is used in conjunction with the
+	  RK3288 HDMI driver.
+
 config DRM_PTN3460
 	tristate "PTN3460 DP/LVDS bridge"
 	depends on DRM
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index eb80dbb..65a1239 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_PS8622) += ps8622.o
 obj-$(CONFIG_DRM_PTN3460) += ptn3460.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw_hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw_hdmi-i2s-audio.o
diff --git a/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c
new file mode 100644
index 0000000..341ab97
--- /dev/null
+++ b/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c
@@ -0,0 +1,398 @@
+/*
+ * DesignWare HDMI audio driver
+ *
+ * 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.
+ *
+ * Written and tested against the Designware HDMI Tx found in RK3288.
+ */
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/pcm_params.h>
+#include <drm/bridge/dw_hdmi.h>
+
+#include "dw_hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-i2s-audio"
+
+enum {
+	AUDIO_CONF1_DATWIDTH_MSK = 0x1F,
+	AUDIO_CONF1_DATAMODE_MSK = 0xE0,
+	AUDIO_DAIFMT_IIS = 0x0,
+	AUDIO_DAIFMT_RIGHT_J = 0x20,
+	AUDIO_DAIFMT_LEFT_J = 0x40,
+	AUDIO_DAIFMT_BURST_1 = 0x60,
+	AUDIO_DAIFMT_BURST_2 = 0x80,
+	AUDIO_CONF0_INTERFACE_MSK = BIT(5),
+	AUDIO_INPUTTYPE_IIS = 0x20,
+	AUDIO_INPUTTYPE_SPDIF = 0x00,
+	AUDIO_CONF0_I2SINEN_MSK = 0x0F,
+	AUDIO_CHANNELNUM_2 = 0x01,
+	AUDIO_CHANNELNUM_4 = 0x03,
+	AUDIO_CHANNELNUM_6 = 0x07,
+	AUDIO_CHANNELNUM_8 = 0x0F,
+	HDMI_PHY_HPD = BIT(1),
+	HDMI_PHY_STAT0 = 0x3004,
+	HDMI_AUD_CONF0 = 0x3100,
+	HDMI_AUD_CONF1 = 0x3101,
+	HDMI_AUD_INPUTCLKFS = 0x3206,
+};
+
+struct dw_audio_fmt {
+	int input_type;
+	int chan_num;
+	int sample_rate;
+	int word_length;
+	int dai_fmt;
+};
+
+struct snd_dw_hdmi {
+	struct device *dev;
+	struct dw_hdmi_audio_data data;
+
+	bool is_jack_ready;
+	struct snd_soc_jack jack;
+
+	bool is_playback_status;
+	struct dw_audio_fmt fmt;
+};
+
+static void hdmi_writel(struct snd_dw_hdmi *dw, u8 val, int offset)
+{
+	writel(val, dw->data.base + (offset << 2));
+}
+
+static u8 hdmi_readl(struct snd_dw_hdmi *dw, int offset)
+{
+	return readl(dw->data.base + (offset << 2));
+}
+
+static void hdmi_modl(struct snd_dw_hdmi *dw, u8 data,
+		      u8 mask, unsigned reg)
+{
+	u8 val = hdmi_readl(dw, reg) & ~mask;
+
+	val |= data & mask;
+	hdmi_writel(dw, val, reg);
+}
+
+int snd_dw_hdmi_jack_detect(struct snd_dw_hdmi *dw)
+{
+	u8 jack_status;
+
+	if (!dw->is_jack_ready)
+		return -EINVAL;
+
+	jack_status = !!(hdmi_readl(dw, HDMI_PHY_STAT0) & HDMI_PHY_HPD) ?
+			SND_JACK_LINEOUT : 0;
+
+	snd_soc_jack_report(&dw->jack, jack_status, SND_JACK_LINEOUT);
+
+	return 0;
+}
+
+static irqreturn_t snd_dw_hdmi_irq(int irq, void *dev_id)
+{
+	struct snd_dw_hdmi *dw = dev_id;
+
+	snd_dw_hdmi_jack_detect(dw);
+
+	return IRQ_HANDLED;
+}
+
+static void dw_hdmi_audio_set_fmt(struct snd_dw_hdmi *dw,
+				  const struct dw_audio_fmt *fmt)
+{
+	hdmi_modl(dw, fmt->input_type, AUDIO_CONF0_INTERFACE_MSK,
+		  HDMI_AUD_CONF0);
+
+	hdmi_modl(dw, fmt->chan_num, AUDIO_CONF0_I2SINEN_MSK,
+		  HDMI_AUD_CONF0);
+
+	hdmi_modl(dw, fmt->word_length, AUDIO_CONF1_DATWIDTH_MSK,
+		  HDMI_AUD_CONF1);
+
+	hdmi_modl(dw, fmt->dai_fmt, AUDIO_CONF1_DATAMODE_MSK,
+		  HDMI_AUD_CONF1);
+
+	hdmi_writel(dw, 0, HDMI_AUD_INPUTCLKFS);
+
+	dw_hdmi_set_sample_rate(dw->data.hdmi, fmt->sample_rate);
+}
+
+static void dw_audio_set_fmt(struct snd_dw_hdmi *dw,
+			     const struct dw_audio_fmt *fmt)
+{
+	if (fmt)
+		dw->fmt = *fmt;
+	dw_hdmi_audio_set_fmt(dw, &dw->fmt);
+}
+
+static int snd_dw_hdmi_dai_startup(struct snd_pcm_substream *substream,
+				   struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *dw = snd_soc_dai_get_drvdata(codec_dai);
+
+	dw->is_playback_status = true;
+	dw_hdmi_audio_enable(dw->data.hdmi);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *dw = snd_soc_dai_get_drvdata(codec_dai);
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct dw_audio_fmt dw_fmt;
+	unsigned int fmt, rate, chan, width;
+
+	fmt = rtd->dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	switch (fmt) {
+	case SND_SOC_DAIFMT_I2S:
+		dw_fmt.dai_fmt = AUDIO_DAIFMT_IIS;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		dw_fmt.dai_fmt = AUDIO_DAIFMT_LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		dw_fmt.dai_fmt = AUDIO_DAIFMT_RIGHT_J;
+		break;
+	default:
+		dev_err(codec_dai->dev, "DAI format unsupported");
+		return -EINVAL;
+	}
+
+	width = params_width(params);
+	switch (width) {
+	case 16:
+	case 24:
+		dw_fmt.word_length = width;
+		break;
+	default:
+		dev_err(codec_dai->dev, "width[%d] not support!\n", width);
+		return -EINVAL;
+	}
+
+	chan = params_channels(params);
+	switch (chan) {
+	case 2:
+		dw_fmt.chan_num = AUDIO_CHANNELNUM_2;
+		break;
+	case 4:
+		dw_fmt.chan_num = AUDIO_CHANNELNUM_4;
+		break;
+	case 6:
+		dw_fmt.chan_num = AUDIO_CHANNELNUM_6;
+		break;
+	case 8:
+		dw_fmt.chan_num = AUDIO_CHANNELNUM_8;
+		break;
+	default:
+		dev_err(codec_dai->dev, "channel[%d] not support!\n", chan);
+		return -EINVAL;
+	}
+
+	rate = params_rate(params);
+	switch (rate) {
+	case 32000:
+	case 44100:
+	case 48000:
+	case 88200:
+	case 96000:
+	case 176400:
+	case 192000:
+		dw_fmt.sample_rate = rate;
+		break;
+	default:
+		dev_err(codec_dai->dev, "rate[%d] not support!\n", rate);
+		return -EINVAL;
+	}
+
+	dw_fmt.input_type = AUDIO_INPUTTYPE_IIS;
+
+	dw_audio_set_fmt(dw, &dw_fmt);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_dai_trigger(struct snd_pcm_substream *substream,
+				   int cmd, struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *dw = snd_soc_dai_get_drvdata(codec_dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		dw_hdmi_audio_enable(dw->data.hdmi);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		dw_hdmi_audio_disable(dw->data.hdmi);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void snd_dw_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
+				     struct snd_soc_dai *codec_dai)
+{
+	struct snd_dw_hdmi *dw = snd_soc_dai_get_drvdata(codec_dai);
+
+	dw->is_playback_status = false;
+	dw_hdmi_audio_disable(dw->data.hdmi);
+}
+
+static int snd_dw_hdmi_audio_probe(struct snd_soc_codec *codec)
+{
+	struct snd_dw_hdmi *dw = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = snd_soc_jack_new(codec, "dw Jack", SND_JACK_LINEOUT,
+			       &dw->jack);
+	if (ret) {
+		dev_err(dw->dev, "jack new failed (%d)\n", ret);
+		dw->is_jack_ready = false;
+		return ret;
+	}
+
+	dw->is_jack_ready = true;
+
+	return snd_dw_hdmi_jack_detect(dw);
+}
+
+static const struct snd_soc_dapm_widget snd_dw_hdmi_audio_widgets[] = {
+	SND_SOC_DAPM_OUTPUT("TX"),
+};
+
+static const struct snd_soc_dapm_route snd_dw_hdmi_audio_routes[] = {
+	{ "TX", NULL, "Playback" },
+};
+
+static const struct snd_soc_dai_ops dw_hdmi_dai_ops = {
+	.startup = snd_dw_hdmi_dai_startup,
+	.hw_params = snd_dw_hdmi_dai_hw_params,
+	.trigger = snd_dw_hdmi_dai_trigger,
+	.shutdown = snd_dw_hdmi_dai_shutdown,
+};
+
+static struct snd_soc_dai_driver dw_hdmi_audio_dai = {
+	.name = "dw-hdmi-i2s-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 2,
+		.channels_max = 8,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+			 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
+			 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+	},
+	.ops = &dw_hdmi_dai_ops,
+};
+
+static const struct snd_soc_codec_driver dw_hdmi_audio = {
+	.probe = snd_dw_hdmi_audio_probe,
+	.dapm_widgets = snd_dw_hdmi_audio_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(snd_dw_hdmi_audio_widgets),
+	.dapm_routes = snd_dw_hdmi_audio_routes,
+	.num_dapm_routes = ARRAY_SIZE(snd_dw_hdmi_audio_routes),
+};
+
+static int dw_hdmi_audio_probe(struct platform_device *pdev)
+{
+	struct dw_hdmi_audio_data *data = pdev->dev.platform_data;
+	struct snd_dw_hdmi *dw;
+	int ret;
+
+	dw = devm_kzalloc(&pdev->dev, sizeof(*dw), GFP_KERNEL);
+	if (!dw)
+		return -ENOMEM;
+
+	dw->data = *data;
+	dw->dev = &pdev->dev;
+	dw->is_jack_ready = false;
+	platform_set_drvdata(pdev, dw);
+
+	ret = request_irq(dw->data.irq, snd_dw_hdmi_irq, IRQF_SHARED,
+			  "dw-dw-audio", dw);
+	if (ret) {
+		dev_err(&pdev->dev, "request irq failed (%d)\n", ret);
+		return -EINVAL;
+	}
+
+	ret = snd_soc_register_codec(&pdev->dev, &dw_hdmi_audio,
+				     &dw_hdmi_audio_dai, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "register codec failed (%d)\n", ret);
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "dw audio init success.\n");
+
+	return 0;
+}
+
+static int dw_hdmi_audio_remove(struct platform_device *pdev)
+{
+	struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
+
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int dw_hdmi_audio_resume(struct device *dev)
+{
+	struct snd_dw_hdmi *dw = dev_get_drvdata(dev);
+
+	snd_dw_hdmi_jack_detect(dw);
+
+	if (dw->is_playback_status)
+		dw_hdmi_audio_set_fmt(dw, &dw->fmt);
+
+	return 0;
+}
+
+static int dw_hdmi_audio_suspend(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops dw_hdmi_audio_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_audio_suspend, dw_hdmi_audio_resume)
+};
+
+static struct platform_driver dw_hdmi_audio_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.pm = &dw_hdmi_audio_pm,
+	},
+	.probe = dw_hdmi_audio_probe,
+	.remove = dw_hdmi_audio_remove,
+};
+module_platform_driver(dw_hdmi_audio_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk at rock-chips.com>");
+MODULE_DESCRIPTION("DW dw Audio ASoC Interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index cbb55ae..5356126 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -1784,20 +1784,26 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 
 	memset(&pdevinfo, 0, sizeof(pdevinfo));
 	pdevinfo.parent = dev;
-	pdevinfo.id = PLATFORM_DEVID_AUTO;
 
-	if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
-		audio.phys = iores->start;
-		audio.base = hdmi->regs;
-		audio.irq = irq;
-		audio.hdmi = hdmi;
-		audio.eld = hdmi->connector.eld;
+	audio.phys = iores->start;
+	audio.base = hdmi->regs;
+	audio.irq = irq;
+	audio.hdmi = hdmi;
+	audio.eld = hdmi->connector.eld;
+
+	pdevinfo.data = &audio;
+	pdevinfo.size_data = sizeof(audio);
 
+	if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
 		pdevinfo.name = "dw-hdmi-ahb-audio";
-		pdevinfo.data = &audio;
-		pdevinfo.size_data = sizeof(audio);
+		pdevinfo.id = PLATFORM_DEVID_AUTO;
 		pdevinfo.dma_mask = DMA_BIT_MASK(32);
 		hdmi->audio = platform_device_register_full(&pdevinfo);
+
+	} else if (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) {
+		pdevinfo.name = "dw-hdmi-ahb-audio";
+		pdevinfo.id = PLATFORM_DEVID_NONE;
+		hdmi->audio = platform_device_register_full(&pdevinfo);
 	}
 
 	dev_set_drvdata(dev, hdmi);
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 78e54e8..9c22377 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -545,6 +545,9 @@
 #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
 
 enum {
+/* CONFIG0_ID field values */
+	HDMI_CONFIG0_I2S = 0x01,
+
 /* CONFIG1_ID field values */
 	HDMI_CONFIG1_AHB = 0x01,
 
-- 
2.1.2




From ykk at rock-chips.com  Fri Jun 19 09:31:05 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:31:05 +0800
Subject: [PATCH v5 5/6] ASoC: rockchip/rockchip-hdmi-audio: add sound driver
 for hdmi audio
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434731465-11106-1-git-send-email-ykk@rock-chips.com>

Add a sound driver that combines rockchip-i2s cpu_dai and dw-hdmi-codec
as codec_dai to provide hdmi audio output on rk3288 platforms.

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5:
- Take Mark Brown suggest that remove the no useful code in probe func,
  and remove the snd_soc_dai_set_fmt() snd_soc_unregister_card(), remove
  those noisy dev_info()
- Rename codec_dai_name to "dw-hdmi-i2s-hifi"

Changes in v4:
- Add ".pm = &snd_soc_pm_ops,"

Changes in v3:
- Delete the operation of jack in rockchip-hdmi-audio driver,
  get ready to switch to simple-audio-card driver.

Changes in v2:
- give "codec-name" & "codec-dai-name" an const name

 sound/soc/rockchip/Kconfig               |   9 ++
 sound/soc/rockchip/Makefile              |   2 +
 sound/soc/rockchip/rockchip_hdmi_audio.c | 138 +++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 sound/soc/rockchip/rockchip_hdmi_audio.c

diff --git a/sound/soc/rockchip/Kconfig b/sound/soc/rockchip/Kconfig
index e181826..ed2b7f0 100644
--- a/sound/soc/rockchip/Kconfig
+++ b/sound/soc/rockchip/Kconfig
@@ -14,3 +14,12 @@ config SND_SOC_ROCKCHIP_I2S
 	  Say Y or M if you want to add support for I2S driver for
 	  Rockchip I2S device. The device supports upto maximum of
 	  8 channels each for play and record.
+
+config SND_SOC_ROCKCHIP_HDMI_AUDIO
+	tristate "ASoC support for Rockchip HDMI audio"
+	depends on SND_SOC_ROCKCHIP
+	select SND_SOC_ROCKCHIP_I2S
+	select SND_SOC_DW_HDMI_AUDIO
+	help
+	  Say Y or M here if you want to add support for SoC audio on Rockchip
+	  HDMI, such as rk3288 hdmi.
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index b921909..b9185b3 100644
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -1,4 +1,6 @@
 # ROCKCHIP Platform Support
 snd-soc-i2s-objs := rockchip_i2s.o
+snd-soc-rockchip-hdmi-audio-objs := rockchip_hdmi_audio.o
 
 obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-i2s.o
+obj-$(CONFIG_SND_SOC_ROCKCHIP_HDMI_AUDIO) += snd-soc-rockchip-hdmi-audio.o
diff --git a/sound/soc/rockchip/rockchip_hdmi_audio.c b/sound/soc/rockchip/rockchip_hdmi_audio.c
new file mode 100644
index 0000000..53ecd60
--- /dev/null
+++ b/sound/soc/rockchip/rockchip_hdmi_audio.c
@@ -0,0 +1,138 @@
+/*
+ * ROCKCHIP ALSA SoC DAI driver for HDMI audio on rockchip processors.
+ * Copyright (c) 2014, ROCKCHIP CORPORATION. All rights reserved.
+ * Authors: Yakir Yang <ykk at rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.*
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/core.h>
+#include <sound/pcm_params.h>
+
+#include "rockchip_i2s.h"
+
+#define DRV_NAME "rockchip-hdmi-audio"
+
+static int rockchip_hdmi_audio_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	unsigned int dai_fmt = rtd->dai_link->dai_fmt;
+	int mclk, ret;
+
+	switch (params_rate(params)) {
+	case 8000:
+	case 16000:
+	case 24000:
+	case 32000:
+	case 48000:
+	case 64000:
+	case 96000:
+		mclk = 12288000;
+		break;
+	case 11025:
+	case 22050:
+	case 44100:
+	case 88200:
+		mclk = 11289600;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, SND_SOC_CLOCK_OUT);
+	if (ret < 0) {
+		dev_err(cpu_dai->dev, "failed to set cpu_dai sysclk.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops hdmi_audio_dai_ops = {
+	.hw_params = rockchip_hdmi_audio_hw_params,
+};
+
+static struct snd_soc_dai_link hdmi_audio_dai = {
+	.name = "RockchipHDMI",
+	.stream_name = "RockchipHDMI",
+	.codec_name = "dw-hdmi-i2s-audio",
+	.codec_dai_name = "dw-hdmi-i2s-hifi",
+	.ops = &hdmi_audio_dai_ops,
+	.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+		   SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card rockchip_hdmi_audio_card = {
+	.name = "RockchipHDMI",
+	.owner = THIS_MODULE,
+	.dai_link = &hdmi_audio_dai,
+	.num_links = 1,
+};
+
+static int rockchip_hdmi_audio_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &rockchip_hdmi_audio_card;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+
+	hdmi_audio_dai.cpu_of_node = of_parse_phandle(np, "i2s-controller", 0);
+	if (!hdmi_audio_dai.cpu_of_node) {
+		dev_err(&pdev->dev, "Property 'i2s-controller' missing !\n");
+		return -EINVAL;
+	}
+
+	hdmi_audio_dai.platform_of_node = hdmi_audio_dai.cpu_of_node;
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "register card failed (%d)\n", ret);
+		card->dev = NULL;
+		return -EINVAL;
+	}
+
+	dev_dbg(&pdev->dev, "hdmi audio init success.\n");
+
+	return 0;
+}
+
+static const struct of_device_id rockchip_hdmi_audio_of_match[] = {
+	{ .compatible = "rockchip,rk3288-hdmi-audio", },
+	{},
+};
+
+static struct platform_driver rockchip_hdmi_audio_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = rockchip_hdmi_audio_of_match,
+	},
+	.probe = rockchip_hdmi_audio_probe,
+};
+module_platform_driver(rockchip_hdmi_audio_driver);
+
+MODULE_AUTHOR("Yakir Yang <ykk at rock-chips.com>");
+MODULE_DESCRIPTION("Rockchip HDMI Audio ASoC Interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, rockchip_hdmi_audio_of_match);
-- 
2.1.2




From linux at arm.linux.org.uk  Fri Jun 19 09:44:12 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Fri, 19 Jun 2015 17:44:12 +0100
Subject: [PATCH v5 1/6] drm: bridge/dw_hdmi: add audio support for more
 display resolutions
In-Reply-To: <1434730752-10829-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434730752-10829-1-git-send-email-ykk@rock-chips.com>
Message-ID: <20150619164411.GU7557@n2100.arm.linux.org.uk>

On Sat, Jun 20, 2015 at 12:19:12AM +0800, Yakir Yang wrote:
> Just like HDMISpecification 1.4 document descripted, the soure shall
> determine the fractional relationship between the TMDS clock an an
> audio reference clock, the sink may then recreate the audio clock from
> the TMDS clock by using an clock divider. So if we can make sink generate
> the correct samplerate, then we can say those display resolutions with
> this pixelclock could support audio play.
> 
> The exact relationship between the two clocks will be:
> 	128 * SampleRate = TmdsClock * N / CTS.
> So this patch would generate the correct N/CTS values, add audio support
> for the below  tmds clocks:
> 25.175MHz, 40MHz, 54MHz, 65MHz, 74.25MHz, 83.5MHz, 106.5MHz, 108Mhz

I think I've said this before.  The documentation for iMX6 (which is
freely available, unlike Rock-chips documentation, so you can look at
it yourself) specifies that only certain audio and video rates are
supported.  See the iMX6 manuals, the section on the HDMI Tx, sub-
section "CTS calculation".

It clearly states that values which do not appear in the table there
are "not supported".

Adding more rates to this code puts iMX6 outside of its specification.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From ykk at rock-chips.com  Fri Jun 19 09:33:21 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Sat, 20 Jun 2015 00:33:21 +0800
Subject: [PATCH v5 6/6] dt-bindings: Add documentation for rockchip-hdmi-audio
 driver
In-Reply-To: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434731601-11152-1-git-send-email-ykk@rock-chips.com>

Required properties:
- compatible: platform specific
- i2s-controller: the i2s controller device node

Signed-off-by: Yakir Yang <ykk at rock-chips.com>
---
Changes in v5: None
Changes in v4: None
Changes in v3:
- modify cpu-of-node to i2s-controller

Changes in v2:
- remove codec-name and codec-dai-name
- rename rockchip,rockchip-hdmi-audio.txt to rockchip,rockchip-dw-hdmi-audio.txt

 .../bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt       | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt

diff --git a/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt b/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
new file mode 100644
index 0000000..f0d23c5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/rockchip,rockchip-dw-hdmi-audio.txt
@@ -0,0 +1,12 @@
+Rockchip hdmi audio bindings
+
+Required properties:
+- compatible: platform specific
+- i2s-controller: the i2s controller device node
+
+Example:
+
+sound {
+	compatible = "rockchip,rk3288-hdmi-audio";
+	i2s-controller = <&i2s>;
+};
-- 
2.1.2




From romain.perier at gmail.com  Sat Jun 20 05:27:16 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Sat, 20 Jun 2015 12:27:16 +0000
Subject: [PATCH] ARM: dts: rockchip: Add STMMAC reset signal in GMAC interface
 for rk3288
Message-ID: <1434803236-20884-1-git-send-email-romain.perier@gmail.com>

Which fixes warning "no reset control found" by the same time

Signed-off-by: Romain Perier <romain.perier at gmail.com>
---
 arch/arm/boot/dts/rk3288.dtsi | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 22316d0..47476d5 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -447,6 +447,8 @@
 			"mac_clk_rx", "mac_clk_tx",
 			"clk_mac_ref", "clk_mac_refout",
 			"aclk_mac", "pclk_mac";
+		resets = <&cru SRST_MAC>;
+		reset-names = "stmmaceth";
 		status = "disabled";
 	};
 
-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 02:44:37 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 17:44:37 +0800
Subject: [PATCH 0/2] add support holding 24Mhz osc during suspend
Message-ID: <1434879879-25162-1-git-send-email-zyw@rock-chips.com>

Since the usb-phy clocks are not connected to the 32khz clock-in, they
only have 24Mhz as the clock source. If we want to wake up system via
usb device, we should hold the 24Mhz osc during suspend.
This Patch has tested on chromebook jerry board, with another patch[0],
we can wakeup system via usb keyboard.

[0] https://chromium-review.googlesource.com/#/c/277811/3


Chris Zhong (2):
  ARM: rockchip: add support holding 24Mhz osc during suspend
  ARM: rockchip: remove some useless macro in pm.h

 arch/arm/mach-rockchip/pm.c | 34 +++++++++++++++++++++++++++++++---
 arch/arm/mach-rockchip/pm.h |  7 -------
 2 files changed, 31 insertions(+), 10 deletions(-)

-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 02:44:38 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 17:44:38 +0800
Subject: [PATCH 1/2] ARM: rockchip: add support holding 24Mhz osc during
 suspend
In-Reply-To: <1434879879-25162-1-git-send-email-zyw@rock-chips.com>
References: <1434879879-25162-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1434879879-25162-2-git-send-email-zyw@rock-chips.com>

If we want to wake up system via usb, the 24Mhz osc could not be
disabled during suspend, read the usb phy SIDDQ bit to decide whether
to switch to 32khz clock-in.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 arch/arm/mach-rockchip/pm.c | 34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
index b0dcbe2..6d32a82 100644
--- a/arch/arm/mach-rockchip/pm.c
+++ b/arch/arm/mach-rockchip/pm.c
@@ -29,6 +29,11 @@
 
 #include "pm.h"
 
+#define GRF_UOC0_CON0			0x320
+#define GRF_UOC1_CON0			0x334
+#define GRF_UOC2_CON0			0x348
+#define GRF_SIDDQ			BIT(13)
+
 /* These enum are option of low power mode */
 enum {
 	ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
@@ -45,6 +50,7 @@ static phys_addr_t rk3288_bootram_phy;
 
 static struct regmap *pmu_regmap;
 static struct regmap *sgrf_regmap;
+static struct regmap *grf_regmap;
 
 static u32 rk3288_pmu_pwr_mode_con;
 static u32 rk3288_sgrf_soc_con0;
@@ -66,9 +72,29 @@ static void rk3288_config_bootdata(void)
 	rkpm_bootdata_l2ctlr = rk3288_l2_config();
 }
 
+static bool rk3288_slp_disable_osc(void)
+{
+	static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
+					  GRF_UOC2_CON0 };
+	u32 reg, i;
+
+	/* if any usb phy is still on(GRF_SIDDQ==0), that means we need the
+	 * function of usb wakeup, so do not switch to 32khz, since the usb phy
+	 * clk does not connect to 32khz osc*/
+	for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
+		regmap_read(grf_regmap, reg_offset[i], &reg);
+		if (!(reg & GRF_SIDDQ))
+			return false;
+	}
+
+	return true;
+}
+
 static void rk3288_slp_mode_set(int level)
 {
-	u32 mode_set, mode_set1;
+	u32 mode_set, mode_set1, osc_switch_to_32k;
+
+	osc_switch_to_32k = rk3288_slp_disable_osc();
 
 	regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
 
@@ -107,11 +133,13 @@ static void rk3288_slp_mode_set(int level)
 
 	if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
 		/* arm off, logic deep sleep */
-		mode_set |= BIT(PMU_BUS_PD_EN) |
+		mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
-			    BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
 
+		if (osc_switch_to_32k)
+			mode_set |= BIT(PMU_OSC_24M_DIS);
+
 		mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
 			     BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
 	} else {
-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 02:44:39 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 17:44:39 +0800
Subject: [PATCH 2/2] ARM: rockchip: remove some useless macro in pm.h
In-Reply-To: <1434879879-25162-1-git-send-email-zyw@rock-chips.com>
References: <1434879879-25162-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1434879879-25162-3-git-send-email-zyw@rock-chips.com>

These are actually not used in the pm code, as we moved suspend handling
to the clock driver, remove them here.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>

---

 arch/arm/mach-rockchip/pm.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
index 3e8d39c..b6494c2 100644
--- a/arch/arm/mach-rockchip/pm.h
+++ b/arch/arm/mach-rockchip/pm.h
@@ -59,13 +59,6 @@ static inline void rockchip_suspend_init(void)
 #define SGRF_DAPDEVICEEN		BIT(0)
 #define SGRF_DAPDEVICEEN_WRITE		BIT(16)
 
-#define RK3288_CRU_MODE_CON		0x50
-#define RK3288_CRU_SEL0_CON		0x60
-#define RK3288_CRU_SEL1_CON		0x64
-#define RK3288_CRU_SEL10_CON		0x88
-#define RK3288_CRU_SEL33_CON		0xe4
-#define RK3288_CRU_SEL37_CON		0xf4
-
 /* PMU_WAKEUP_CFG1 bits */
 #define PMU_ARMINT_WAKEUP_EN		BIT(0)
 
-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 03:00:45 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 18:00:45 +0800
Subject: [PATCH v2 0/2] add support holding 24Mhz osc during suspend
Message-ID: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>

Since the usb-phy clocks are not connected to the 32khz clock-in, they
only have 24Mhz as the clock source. If we want to wake up system via
usb device, we should hold the 24Mhz osc during suspend.
This Patch has tested on chromebook jerry board, with another patch[0],
we can wakeup system via usb keyboard.

[0] https://chromium-review.googlesource.com/#/c/277811/3


Chris Zhong (2):
  ARM: rockchip: add support holding 24Mhz osc during suspend
  ARM: rockchip: remove some useless macro in pm.h

 arch/arm/mach-rockchip/pm.c | 38 ++++++++++++++++++++++++++++++++++++--
 arch/arm/mach-rockchip/pm.h |  7 -------
 2 files changed, 36 insertions(+), 9 deletions(-)

-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 03:00:46 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 18:00:46 +0800
Subject: [PATCH v2 1/2] ARM: rockchip: add support holding 24Mhz osc during
 suspend
In-Reply-To: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
References: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1434880847-29505-2-git-send-email-zyw@rock-chips.com>

If we want to wake up system via usb, the 24Mhz osc could not be
disabled during suspend, read the usb phy SIDDQ bit to decide whether
to switch to 32khz clock-in.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
---

 arch/arm/mach-rockchip/pm.c | 38 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 36 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
index b0dcbe2..fda81d3 100644
--- a/arch/arm/mach-rockchip/pm.c
+++ b/arch/arm/mach-rockchip/pm.c
@@ -29,6 +29,11 @@
 
 #include "pm.h"
 
+#define GRF_UOC0_CON0			0x320
+#define GRF_UOC1_CON0			0x334
+#define GRF_UOC2_CON0			0x348
+#define GRF_SIDDQ			BIT(13)
+
 /* These enum are option of low power mode */
 enum {
 	ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0,
@@ -45,6 +50,7 @@ static phys_addr_t rk3288_bootram_phy;
 
 static struct regmap *pmu_regmap;
 static struct regmap *sgrf_regmap;
+static struct regmap *grf_regmap;
 
 static u32 rk3288_pmu_pwr_mode_con;
 static u32 rk3288_sgrf_soc_con0;
@@ -66,9 +72,28 @@ static void rk3288_config_bootdata(void)
 	rkpm_bootdata_l2ctlr = rk3288_l2_config();
 }
 
+static bool rk3288_slp_disable_osc(void)
+{
+	static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
+					  GRF_UOC2_CON0 };
+	u32 reg, i;
+
+	/* if any usb phy is still on(GRF_SIDDQ==0), that means we need the
+	 * function of usb wakeup, so do not switch to 32khz, since the usb phy
+	 * clk does not connect to 32khz osc*/
+	for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
+		regmap_read(grf_regmap, reg_offset[i], &reg);
+		if (!(reg & GRF_SIDDQ))
+			return false;
+	}
+
+	return true;
+}
+
 static void rk3288_slp_mode_set(int level)
 {
 	u32 mode_set, mode_set1;
+	bool osc_switch_to_32k = rk3288_slp_disable_osc();
 
 	regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
 
@@ -107,11 +132,13 @@ static void rk3288_slp_mode_set(int level)
 
 	if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
 		/* arm off, logic deep sleep */
-		mode_set |= BIT(PMU_BUS_PD_EN) |
+		mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
-			    BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
 
+		if (osc_switch_to_32k)
+			mode_set |= BIT(PMU_OSC_24M_DIS);
+
 		mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
 			     BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
 	} else {
@@ -193,6 +220,13 @@ static int rk3288_suspend_init(struct device_node *np)
 		return PTR_ERR(pmu_regmap);
 	}
 
+	grf_regmap = syscon_regmap_lookup_by_compatible(
+				"rockchip,rk3288-grf");
+	if (IS_ERR(grf_regmap)) {
+		pr_err("%s: could not find grf regmap\n", __func__);
+		return PTR_ERR(pmu_regmap);
+	}
+
 	sram_np = of_find_compatible_node(NULL, NULL,
 					  "rockchip,rk3288-pmu-sram");
 	if (!sram_np) {
-- 
1.9.1



From zyw at rock-chips.com  Sun Jun 21 03:00:47 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Sun, 21 Jun 2015 18:00:47 +0800
Subject: [PATCH v2 2/2] ARM: rockchip: remove some useless macro in pm.h
In-Reply-To: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
References: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1434880847-29505-3-git-send-email-zyw@rock-chips.com>

These are actually not used in the pm code, as we moved suspend handling
to the clock driver, remove them here.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>

---

 arch/arm/mach-rockchip/pm.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
index 3e8d39c..b6494c2 100644
--- a/arch/arm/mach-rockchip/pm.h
+++ b/arch/arm/mach-rockchip/pm.h
@@ -59,13 +59,6 @@ static inline void rockchip_suspend_init(void)
 #define SGRF_DAPDEVICEEN		BIT(0)
 #define SGRF_DAPDEVICEEN_WRITE		BIT(16)
 
-#define RK3288_CRU_MODE_CON		0x50
-#define RK3288_CRU_SEL0_CON		0x60
-#define RK3288_CRU_SEL1_CON		0x64
-#define RK3288_CRU_SEL10_CON		0x88
-#define RK3288_CRU_SEL33_CON		0xe4
-#define RK3288_CRU_SEL37_CON		0xf4
-
 /* PMU_WAKEUP_CFG1 bits */
 #define PMU_ARMINT_WAKEUP_EN		BIT(0)
 
-- 
1.9.1



From davem at davemloft.net  Sun Jun 21 10:32:58 2015
From: davem at davemloft.net (David Miller)
Date: Sun, 21 Jun 2015 10:32:58 -0700 (PDT)
Subject: [PATCH 0/4] net: stmmac: dwmac-rk: add support for rk3368
In-Reply-To: <1434578086-12209-1-git-send-email-heiko@sntech.de>
References: <1434578086-12209-1-git-send-email-heiko@sntech.de>
Message-ID: <20150621.103258.310307194495952422.davem@davemloft.net>

From: Heiko Stuebner <heiko at sntech.de>
Date: Wed, 17 Jun 2015 23:54:42 +0200

> Apart from small cleanups, this series provides support for the dwmac
> on the new rk3368 ARM64 soc.
> 
> Tested on a R88 board using a RMII phy.

These patches do not apply to the net-next tree, please respin
and resubmit.

Thanks.


From heiko at sntech.de  Sun Jun 21 12:52:50 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 21 Jun 2015 21:52:50 +0200
Subject: [PATCH v2 0/4] net: stmmac: dwmac-rk: add support for rk3368
Message-ID: <1434916374-7457-1-git-send-email-heiko@sntech.de>

Apart from small cleanups, this series provides support for the dwmac
on the new rk3368 ARM64 soc.

Tested on a R88 board using a RMII phy.

Changes since v1:
- Adapt to changes resulting from patch d42202dce002 ("net: stmmac:
dwmac-rk: Don't add function name in info or err messages")


Heiko Stuebner (4):
  net: stmmac: dwmac-rk: remove unused gpio register defines
  net: stmmac: dwmac-rk: Fix clk rate when provided by soc
  net: stmmac: dwmac-rk: abstract access to mac settings in GRF
  net: stmmac: dwmac-rk: add rk3368-specific data

 .../devicetree/bindings/net/rockchip-dwmac.txt     |   2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c     | 248 +++++++++++++++++----
 2 files changed, 203 insertions(+), 47 deletions(-)

-- 
2.1.4



From heiko at sntech.de  Sun Jun 21 12:52:51 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 21 Jun 2015 21:52:51 +0200
Subject: [PATCH v2 1/4] net: stmmac: dwmac-rk: remove unused gpio register
 defines
In-Reply-To: <1434916374-7457-1-git-send-email-heiko@sntech.de>
References: <1434916374-7457-1-git-send-email-heiko@sntech.de>
Message-ID: <1434916374-7457-2-git-send-email-heiko@sntech.de>

In a first version the driver did want to do some gpio wiggling, which
of course never made it into the kernel, but somehow these register
defines where forgotten. Remove them, as they shouldn't be here.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 26c339d..a396070 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -65,9 +65,6 @@ struct rk_priv_data {
 
 #define RK3288_GRF_SOC_CON1	0x0248
 #define RK3288_GRF_SOC_CON3	0x0250
-#define RK3288_GRF_GPIO3D_E	0x01ec
-#define RK3288_GRF_GPIO4A_E	0x01f0
-#define RK3288_GRF_GPIO4B_E	0x01f4
 
 /*RK3288_GRF_SOC_CON1*/
 #define GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
-- 
2.1.4



From heiko at sntech.de  Sun Jun 21 12:52:54 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 21 Jun 2015 21:52:54 +0200
Subject: [PATCH v2 4/4] net: stmmac: dwmac-rk: add rk3368-specific data
In-Reply-To: <1434916374-7457-1-git-send-email-heiko@sntech.de>
References: <1434916374-7457-1-git-send-email-heiko@sntech.de>
Message-ID: <1434916374-7457-5-git-send-email-heiko@sntech.de>

Add constants and callback functions for the dwmac on rk3368 socs.
As can be seen, the base structure is the same, only registers and
the bits in them moved slightly.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 .../devicetree/bindings/net/rockchip-dwmac.txt     |   2 +-
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c     | 126 +++++++++++++++++++++
 2 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
index 21fd199..93eac7c 100644
--- a/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.txt
@@ -3,7 +3,7 @@ Rockchip SoC RK3288 10/100/1000 Ethernet driver(GMAC)
 The device node has following properties.
 
 Required properties:
- - compatible: Can be "rockchip,rk3288-gmac".
+ - compatible: Can be one of "rockchip,rk3288-gmac", "rockchip,rk3368-gmac"
  - reg: addresses and length of the register sets for the device.
  - interrupts: Should contain the GMAC interrupts.
  - interrupt-names: Should contain the interrupt names "macirq".
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 65afca6..00a1e1e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -184,6 +184,118 @@ struct rk_gmac_ops rk3288_ops = {
 	.set_rmii_speed = rk3288_set_rmii_speed,
 };
 
+#define RK3368_GRF_SOC_CON15	0x043c
+#define RK3368_GRF_SOC_CON16	0x0440
+
+/* RK3368_GRF_SOC_CON15 */
+#define RK3368_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(9) | GRF_CLR_BIT(10) | \
+					 GRF_CLR_BIT(11))
+#define RK3368_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(9) | GRF_CLR_BIT(10) | \
+					 GRF_BIT(11))
+#define RK3368_GMAC_FLOW_CTRL		GRF_BIT(8)
+#define RK3368_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(8)
+#define RK3368_GMAC_SPEED_10M		GRF_CLR_BIT(7)
+#define RK3368_GMAC_SPEED_100M		GRF_BIT(7)
+#define RK3368_GMAC_RMII_CLK_25M	GRF_BIT(3)
+#define RK3368_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(3)
+#define RK3368_GMAC_CLK_125M		(GRF_CLR_BIT(4) | GRF_CLR_BIT(5))
+#define RK3368_GMAC_CLK_25M		(GRF_BIT(4) | GRF_BIT(5))
+#define RK3368_GMAC_CLK_2_5M		(GRF_CLR_BIT(4) | GRF_BIT(5))
+#define RK3368_GMAC_RMII_MODE		GRF_BIT(6)
+#define RK3368_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(6)
+
+/* RK3368_GRF_SOC_CON16 */
+#define RK3368_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(7)
+#define RK3368_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(7)
+#define RK3368_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3368_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3368_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 8)
+#define RK3368_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
+
+static void rk3368_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+		     RK3368_GMAC_PHY_INTF_SEL_RGMII |
+		     RK3368_GMAC_RMII_MODE_CLR);
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON16,
+		     RK3368_GMAC_RXCLK_DLY_ENABLE |
+		     RK3368_GMAC_TXCLK_DLY_ENABLE |
+		     RK3368_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3368_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3368_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+		     RK3368_GMAC_PHY_INTF_SEL_RMII | RK3368_GMAC_RMII_MODE);
+}
+
+static void rk3368_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	if (speed == 10)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_2_5M);
+	else if (speed == 100)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_25M);
+	else if (speed == 1000)
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_CLK_125M);
+	else
+		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3368_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+	struct device *dev = &bsp_priv->pdev->dev;
+
+	if (IS_ERR(bsp_priv->grf)) {
+		dev_err(dev, "%s: Missing rockchip,grf property\n", __func__);
+		return;
+	}
+
+	if (speed == 10) {
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_RMII_CLK_2_5M |
+			     RK3368_GMAC_SPEED_10M);
+	} else if (speed == 100) {
+		regmap_write(bsp_priv->grf, RK3368_GRF_SOC_CON15,
+			     RK3368_GMAC_RMII_CLK_25M |
+			     RK3368_GMAC_SPEED_100M);
+	} else {
+		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+	}
+}
+
+struct rk_gmac_ops rk3368_ops = {
+	.set_to_rgmii = rk3368_set_to_rgmii,
+	.set_to_rmii = rk3368_set_to_rmii,
+	.set_rgmii_speed = rk3368_set_rgmii_speed,
+	.set_rmii_speed = rk3368_set_rmii_speed,
+};
+
 static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
@@ -422,6 +534,11 @@ static void *rk3288_gmac_setup(struct platform_device *pdev)
 	return rk_gmac_setup(pdev, &rk3288_ops);
 }
 
+static void *rk3368_gmac_setup(struct platform_device *pdev)
+{
+	return rk_gmac_setup(pdev, &rk3368_ops);
+}
+
 static int rk_gmac_init(struct platform_device *pdev, void *priv)
 {
 	struct rk_priv_data *bsp_priv = priv;
@@ -467,8 +584,17 @@ static const struct stmmac_of_data rk3288_gmac_data = {
 	.exit = rk_gmac_exit,
 };
 
+static const struct stmmac_of_data rk3368_gmac_data = {
+	.has_gmac = 1,
+	.fix_mac_speed = rk_fix_speed,
+	.setup = rk3368_gmac_setup,
+	.init = rk_gmac_init,
+	.exit = rk_gmac_exit,
+};
+
 static const struct of_device_id rk_gmac_dwmac_match[] = {
 	{ .compatible = "rockchip,rk3288-gmac", .data = &rk3288_gmac_data},
+	{ .compatible = "rockchip,rk3368-gmac", .data = &rk3368_gmac_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, rk_gmac_dwmac_match);
-- 
2.1.4



From heiko at sntech.de  Sun Jun 21 12:52:52 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 21 Jun 2015 21:52:52 +0200
Subject: [PATCH v2 2/4] net: stmmac: dwmac-rk: Fix clk rate when provided by
 soc
In-Reply-To: <1434916374-7457-1-git-send-email-heiko@sntech.de>
References: <1434916374-7457-1-git-send-email-heiko@sntech.de>
Message-ID: <1434916374-7457-3-git-send-email-heiko@sntech.de>

The first iteration of the dwmac-rk support did access an intermediate
clock directly below the pll selector. This was removed in a subsequent
revision, but the clock and one invocation remained. This results in
the driver trying to set the rate of a non-existent clock when the soc
and not some external source provides the phy clock for RMII phys.

So set the rate of the correct clock and remove the remaining now
completely unused definition.

Fixes: 436f5ae08f9d ("GMAC: add driver for Rockchip RK3288 SoCs integrated GMAC")
Cc: stable at vger.kernel.org
Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index a396070..5dafebb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -42,7 +42,6 @@ struct rk_priv_data {
 	bool clock_input;
 
 	struct clk *clk_mac;
-	struct clk *clk_mac_pll;
 	struct clk *gmac_clkin;
 	struct clk *mac_clk_rx;
 	struct clk *mac_clk_tx;
@@ -209,7 +208,7 @@ static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 		dev_info(dev, "clock input from PHY\n");
 	} else {
 		if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-			clk_set_rate(bsp_priv->clk_mac_pll, 50000000);
+			clk_set_rate(bsp_priv->clk_mac, 50000000);
 	}
 
 	return 0;
-- 
2.1.4



From heiko at sntech.de  Sun Jun 21 12:52:53 2015
From: heiko at sntech.de (Heiko Stuebner)
Date: Sun, 21 Jun 2015 21:52:53 +0200
Subject: [PATCH v2 3/4] net: stmmac: dwmac-rk: abstract access to mac settings
 in GRF
In-Reply-To: <1434916374-7457-1-git-send-email-heiko@sntech.de>
References: <1434916374-7457-1-git-send-email-heiko@sntech.de>
Message-ID: <1434916374-7457-4-git-send-email-heiko@sntech.de>

The mac settings like RGMII/RMII, speeds etc are done in the so called
"General Register Files", contain numerous other settings as well and
always seem to change between Rockchip SoCs. Therefore abstract the
register accesses into a per-soc ops struct to make this reusable on
other Rockchip SoCs.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 116 ++++++++++++++++---------
 1 file changed, 75 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 5dafebb..65afca6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -33,10 +33,20 @@
 
 #include "stmmac_platform.h"
 
+struct rk_priv_data;
+struct rk_gmac_ops {
+	void (*set_to_rgmii)(struct rk_priv_data *bsp_priv,
+			     int tx_delay, int rx_delay);
+	void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
+	void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
+	void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
+};
+
 struct rk_priv_data {
 	struct platform_device *pdev;
 	int phy_iface;
 	struct regulator *regulator;
+	struct rk_gmac_ops *ops;
 
 	bool clk_enabled;
 	bool clock_input;
@@ -66,30 +76,32 @@ struct rk_priv_data {
 #define RK3288_GRF_SOC_CON3	0x0250
 
 /*RK3288_GRF_SOC_CON1*/
-#define GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
-#define GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8))
-#define GMAC_FLOW_CTRL		GRF_BIT(9)
-#define GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
-#define GMAC_SPEED_10M		GRF_CLR_BIT(10)
-#define GMAC_SPEED_100M		GRF_BIT(10)
-#define GMAC_RMII_CLK_25M	GRF_BIT(11)
-#define GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
-#define GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
-#define GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
-#define GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
-#define GMAC_RMII_MODE		GRF_BIT(14)
-#define GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
+#define RK3288_GMAC_PHY_INTF_SEL_RGMII	(GRF_BIT(6) | GRF_CLR_BIT(7) | \
+					 GRF_CLR_BIT(8))
+#define RK3288_GMAC_PHY_INTF_SEL_RMII	(GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | \
+					 GRF_BIT(8))
+#define RK3288_GMAC_FLOW_CTRL		GRF_BIT(9)
+#define RK3288_GMAC_FLOW_CTRL_CLR	GRF_CLR_BIT(9)
+#define RK3288_GMAC_SPEED_10M		GRF_CLR_BIT(10)
+#define RK3288_GMAC_SPEED_100M		GRF_BIT(10)
+#define RK3288_GMAC_RMII_CLK_25M	GRF_BIT(11)
+#define RK3288_GMAC_RMII_CLK_2_5M	GRF_CLR_BIT(11)
+#define RK3288_GMAC_CLK_125M		(GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
+#define RK3288_GMAC_CLK_25M		(GRF_BIT(12) | GRF_BIT(13))
+#define RK3288_GMAC_CLK_2_5M		(GRF_CLR_BIT(12) | GRF_BIT(13))
+#define RK3288_GMAC_RMII_MODE		GRF_BIT(14)
+#define RK3288_GMAC_RMII_MODE_CLR	GRF_CLR_BIT(14)
 
 /*RK3288_GRF_SOC_CON3*/
-#define GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
-#define GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
-#define GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
-#define GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
-#define GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
-#define GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
-
-static void set_to_rgmii(struct rk_priv_data *bsp_priv,
-			 int tx_delay, int rx_delay)
+#define RK3288_GMAC_TXCLK_DLY_ENABLE	GRF_BIT(14)
+#define RK3288_GMAC_TXCLK_DLY_DISABLE	GRF_CLR_BIT(14)
+#define RK3288_GMAC_RXCLK_DLY_ENABLE	GRF_BIT(15)
+#define RK3288_GMAC_RXCLK_DLY_DISABLE	GRF_CLR_BIT(15)
+#define RK3288_GMAC_CLK_RX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 7)
+#define RK3288_GMAC_CLK_TX_DL_CFG(val)	HIWORD_UPDATE(val, 0x7F, 0)
+
+static void rk3288_set_to_rgmii(struct rk_priv_data *bsp_priv,
+				int tx_delay, int rx_delay)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -99,14 +111,16 @@ static void set_to_rgmii(struct rk_priv_data *bsp_priv,
 	}
 
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-		     GMAC_PHY_INTF_SEL_RGMII | GMAC_RMII_MODE_CLR);
+		     RK3288_GMAC_PHY_INTF_SEL_RGMII |
+		     RK3288_GMAC_RMII_MODE_CLR);
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON3,
-		     GMAC_RXCLK_DLY_ENABLE | GMAC_TXCLK_DLY_ENABLE |
-		     GMAC_CLK_RX_DL_CFG(rx_delay) |
-		     GMAC_CLK_TX_DL_CFG(tx_delay));
+		     RK3288_GMAC_RXCLK_DLY_ENABLE |
+		     RK3288_GMAC_TXCLK_DLY_ENABLE |
+		     RK3288_GMAC_CLK_RX_DL_CFG(rx_delay) |
+		     RK3288_GMAC_CLK_TX_DL_CFG(tx_delay));
 }
 
-static void set_to_rmii(struct rk_priv_data *bsp_priv)
+static void rk3288_set_to_rmii(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -116,10 +130,10 @@ static void set_to_rmii(struct rk_priv_data *bsp_priv)
 	}
 
 	regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-		     GMAC_PHY_INTF_SEL_RMII | GMAC_RMII_MODE);
+		     RK3288_GMAC_PHY_INTF_SEL_RMII | RK3288_GMAC_RMII_MODE);
 }
 
-static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+static void rk3288_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -129,16 +143,19 @@ static void set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
 	}
 
 	if (speed == 10)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_2_5M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_2_5M);
 	else if (speed == 100)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_25M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_25M);
 	else if (speed == 1000)
-		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1, GMAC_CLK_125M);
+		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
+			     RK3288_GMAC_CLK_125M);
 	else
 		dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
 }
 
-static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+static void rk3288_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
 
@@ -149,15 +166,24 @@ static void set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
 
 	if (speed == 10) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-			     GMAC_RMII_CLK_2_5M | GMAC_SPEED_10M);
+			     RK3288_GMAC_RMII_CLK_2_5M |
+			     RK3288_GMAC_SPEED_10M);
 	} else if (speed == 100) {
 		regmap_write(bsp_priv->grf, RK3288_GRF_SOC_CON1,
-			     GMAC_RMII_CLK_25M | GMAC_SPEED_100M);
+			     RK3288_GMAC_RMII_CLK_25M |
+			     RK3288_GMAC_SPEED_100M);
 	} else {
 		dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
 	}
 }
 
+struct rk_gmac_ops rk3288_ops = {
+	.set_to_rgmii = rk3288_set_to_rgmii,
+	.set_to_rmii = rk3288_set_to_rmii,
+	.set_rgmii_speed = rk3288_set_rgmii_speed,
+	.set_rmii_speed = rk3288_set_rmii_speed,
+};
+
 static int gmac_clk_init(struct rk_priv_data *bsp_priv)
 {
 	struct device *dev = &bsp_priv->pdev->dev;
@@ -309,7 +335,8 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
 	return 0;
 }
 
-static void *rk_gmac_setup(struct platform_device *pdev)
+static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
+					  struct rk_gmac_ops *ops)
 {
 	struct rk_priv_data *bsp_priv;
 	struct device *dev = &pdev->dev;
@@ -322,6 +349,7 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 		return ERR_PTR(-ENOMEM);
 
 	bsp_priv->phy_iface = of_get_phy_mode(dev->of_node);
+	bsp_priv->ops = ops;
 
 	bsp_priv->regulator = devm_regulator_get_optional(dev, "phy");
 	if (IS_ERR(bsp_priv->regulator)) {
@@ -375,10 +403,11 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 	/*rmii or rgmii*/
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII) {
 		dev_info(dev, "init for RGMII\n");
-		set_to_rgmii(bsp_priv, bsp_priv->tx_delay, bsp_priv->rx_delay);
+		bsp_priv->ops->set_to_rgmii(bsp_priv, bsp_priv->tx_delay,
+					    bsp_priv->rx_delay);
 	} else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII) {
 		dev_info(dev, "init for RMII\n");
-		set_to_rmii(bsp_priv);
+		bsp_priv->ops->set_to_rmii(bsp_priv);
 	} else {
 		dev_err(dev, "NO interface defined!\n");
 	}
@@ -388,6 +417,11 @@ static void *rk_gmac_setup(struct platform_device *pdev)
 	return bsp_priv;
 }
 
+static void *rk3288_gmac_setup(struct platform_device *pdev)
+{
+	return rk_gmac_setup(pdev, &rk3288_ops);
+}
+
 static int rk_gmac_init(struct platform_device *pdev, void *priv)
 {
 	struct rk_priv_data *bsp_priv = priv;
@@ -418,9 +452,9 @@ static void rk_fix_speed(void *priv, unsigned int speed)
 	struct device *dev = &bsp_priv->pdev->dev;
 
 	if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RGMII)
-		set_rgmii_speed(bsp_priv, speed);
+		bsp_priv->ops->set_rgmii_speed(bsp_priv, speed);
 	else if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
-		set_rmii_speed(bsp_priv, speed);
+		bsp_priv->ops->set_rmii_speed(bsp_priv, speed);
 	else
 		dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface);
 }
@@ -428,7 +462,7 @@ static void rk_fix_speed(void *priv, unsigned int speed)
 static const struct stmmac_of_data rk3288_gmac_data = {
 	.has_gmac = 1,
 	.fix_mac_speed = rk_fix_speed,
-	.setup = rk_gmac_setup,
+	.setup = rk3288_gmac_setup,
 	.init = rk_gmac_init,
 	.exit = rk_gmac_exit,
 };
-- 
2.1.4



From pebolle at tiscali.nl  Mon Jun 22 03:06:04 2015
From: pebolle at tiscali.nl (Paul Bolle)
Date: Mon, 22 Jun 2015 12:06:04 +0200
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
Message-ID: <1434967564.31094.20.camel@x220>

Something I didn't notice in v4, sorry.

On Sat, 2015-06-20 at 00:28 +0800, Yakir Yang wrote:
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c

> +#define DRIVER_NAME "dw-hdmi-i2s-audio"

> +MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);

0) Side note: this is the first time that PLATFORM_MODULE_PREFIX is used
inside MODULE_ALIAS(). But none of the 1000+ other "platform:" aliases
do that. And neither does 5/6 of this series! That suggests, I think,
that this shouldn't be done.

You could consider adding something like
    #define MODULE_ALIAS_PLATFORM(NAME) MODULE_ALIAS(PLATFORM_MODULE_PREFIX NAME)

But then, I think, all the current 1000+ platform: aliases should be
converted to that macro. Would that be worth it?

1) Now on to my remark: this alias seems to be only useful if there also
is a struct platform_device with a "dw-hdmi-i2s-audio" name. Because
that platform_device would, badly summarized, fire of a
"MODALIAS=platform:dw-hdmi-i2s-audio" uevent when created. Which, in its
turn, would trigger userspace to load this module, correct?

But I think there's no platform_device with a "dw-hdmi-i2s-audio" name.
So I wonder whether this MODULE_ALIAS() is actually needed. What breaks
if you leave it out?

(Likewise for 5/6, but there the platform_device should have a
"rockchip-hdmi-audio" name.)

Thanks,


Paul Bolle



From linux at arm.linux.org.uk  Mon Jun 22 03:10:38 2015
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Mon, 22 Jun 2015 11:10:38 +0100
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <1434967564.31094.20.camel@x220>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
 <1434967564.31094.20.camel@x220>
Message-ID: <20150622101038.GV7557@n2100.arm.linux.org.uk>

On Mon, Jun 22, 2015 at 12:06:04PM +0200, Paul Bolle wrote:
> But I think there's no platform_device with a "dw-hdmi-i2s-audio" name.
> So I wonder whether this MODULE_ALIAS() is actually needed. What breaks
> if you leave it out?

+       } else if (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) {
+               pdevinfo.name = "dw-hdmi-ahb-audio";

This should be "dw-hdmi-i2s-audio" to avoid picking up on my AHB audio
driver.

-- 
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.


From heiko at sntech.de  Mon Jun 22 07:32:11 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 22 Jun 2015 16:32:11 +0200
Subject: [PATCH] ARM: dts: rockchip: Add STMMAC reset signal in GMAC
 interface for rk3288
In-Reply-To: <1434803236-20884-1-git-send-email-romain.perier@gmail.com>
References: <1434803236-20884-1-git-send-email-romain.perier@gmail.com>
Message-ID: <7844042.9mqzGAIf34@diego>

Am Samstag, 20. Juni 2015, 12:27:16 schrieb Romain Perier:
> Which fixes warning "no reset control found" by the same time
> 
> Signed-off-by: Romain Perier <romain.perier at gmail.com>

applied to dts changes for 4.3


From heiko at sntech.de  Mon Jun 22 07:36:00 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 22 Jun 2015 16:36 +0200
Subject: [PATCH] ARM: dts: rockchip: Add ramp delay for vdd_cpu in firefly
 board dts
In-Reply-To: <1434390101-27000-1-git-send-email-romain.perier@gmail.com>
References: <1434390101-27000-1-git-send-email-romain.perier@gmail.com>
Message-ID: <239166562.834dQUR87q@diego>

Am Montag, 15. Juni 2015, 17:41:41 schrieb Romain Perier:
> Adds ramp delay for the vdd_cpu output. It removes warning "ramp_delay not
> set" emitted by the function regulator_set_voltage_time_sel() by the same
> time, which floods kernel logs.
> 
> Signed-off-by: Romain Perier <romain.perier at gmail.com>
> ---

applied to dts changes for 4.3


From heiko at sntech.de  Mon Jun 22 07:38:10 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 22 Jun 2015 16:38:10 +0200
Subject: [PATCH] ARM: dts: rockchip: fix rk3288 watchdog irq
In-Reply-To: <1961157.dsytR1KvKa@phil>
References: <1961157.dsytR1KvKa@phil>
Message-ID: <4785881.zacpjkQbnc@diego>

Am Freitag, 19. Juni 2015, 16:31:14 schrieb Heiko Stuebner:
> The watchdog irq is actually SPI 79, which translates to the original
> 111 in the manual where the SPI irqs start at 32.
> The current dw_wdt driver does not use the irq at all, so this issue
> never surfaced. Nevertheless fix this for a time we want to use the irq.
> 
> Fixes: 2ab557b72d46 ("ARM: dts: rockchip: add core rk3288 dtsi")
> Signed-off-by: Heiko Stuebner <heiko at sntech.de>

applied to dts changes for 4.3


From dianders at chromium.org  Mon Jun 22 08:25:59 2015
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 22 Jun 2015 08:25:59 -0700
Subject: [RESEND PATCH] ARM: dts: cros-ec-keyboard: Add support for some
 Japanese keys
In-Reply-To: <1430874218-27738-1-git-send-email-zyw@rock-chips.com>
References: <1430874218-27738-1-git-send-email-zyw@rock-chips.com>
Message-ID: <CAD=FV=U2BpMqBdOCihc9CAc2Q0gvECgH9Qm8e1XvQ-4ftWqrBA@mail.gmail.com>

Hi,

On Tue, May 5, 2015 at 6:03 PM, Chris Zhong <zyw at rock-chips.com> wrote:
> Add support for 4 Japanese keys
>
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> Reviewed-by: Doug Anderson <dianders at chromium.org>
>
> ---
>
>  arch/arm/boot/dts/cros-ec-keyboard.dtsi | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/cros-ec-keyboard.dtsi b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
> index 9c7fb0a..4e42f30c 100644
> --- a/arch/arm/boot/dts/cros-ec-keyboard.dtsi
> +++ b/arch/arm/boot/dts/cros-ec-keyboard.dtsi
> @@ -22,6 +22,7 @@
>                         MATRIX_KEY(0x00, 0x02, KEY_F1)
>                         MATRIX_KEY(0x00, 0x03, KEY_B)
>                         MATRIX_KEY(0x00, 0x04, KEY_F10)
> +                       MATRIX_KEY(0x00, 0x05, KEY_RO)
>                         MATRIX_KEY(0x00, 0x06, KEY_N)
>                         MATRIX_KEY(0x00, 0x08, KEY_EQUAL)
>                         MATRIX_KEY(0x00, 0x0a, KEY_RIGHTALT)
> @@ -34,6 +35,7 @@
>                         MATRIX_KEY(0x01, 0x08, KEY_APOSTROPHE)
>                         MATRIX_KEY(0x01, 0x09, KEY_F9)
>                         MATRIX_KEY(0x01, 0x0b, KEY_BACKSPACE)
> +                       MATRIX_KEY(0x01, 0x0c, KEY_HENKAN)
>
>                         MATRIX_KEY(0x02, 0x00, KEY_LEFTCTRL)
>                         MATRIX_KEY(0x02, 0x01, KEY_TAB)
> @@ -45,6 +47,7 @@
>                         MATRIX_KEY(0x02, 0x07, KEY_102ND)
>                         MATRIX_KEY(0x02, 0x08, KEY_LEFTBRACE)
>                         MATRIX_KEY(0x02, 0x09, KEY_F8)
> +                       MATRIX_KEY(0x02, 0x0a, KEY_YEN)
>
>                         MATRIX_KEY(0x03, 0x01, KEY_GRAVE)
>                         MATRIX_KEY(0x03, 0x02, KEY_F2)
> @@ -53,6 +56,7 @@
>                         MATRIX_KEY(0x03, 0x06, KEY_6)
>                         MATRIX_KEY(0x03, 0x08, KEY_MINUS)
>                         MATRIX_KEY(0x03, 0x0b, KEY_BACKSLASH)
> +                       MATRIX_KEY(0x03, 0x0c, KEY_MUHENKAN)
>
>                         MATRIX_KEY(0x04, 0x00, KEY_RIGHTCTRL)
>                         MATRIX_KEY(0x04, 0x01, KEY_A)
> --
> 1.9.1

Is anyone planning to pick up this trivial change?

-Doug


From dianders at chromium.org  Mon Jun 22 12:59:19 2015
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 22 Jun 2015 12:59:19 -0700
Subject: [PATCH v2 2/2] ARM: rockchip: remove some useless macro in pm.h
In-Reply-To: <1434880847-29505-3-git-send-email-zyw@rock-chips.com>
References: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
 <1434880847-29505-3-git-send-email-zyw@rock-chips.com>
Message-ID: <CAD=FV=Xa_T-L+mU77gfo9Vau9Q4KcJ=RTYzHcbv05=4Xy8R-8w@mail.gmail.com>

Chris,

On Sun, Jun 21, 2015 at 3:00 AM, Chris Zhong <zyw at rock-chips.com> wrote:
> These are actually not used in the pm code, as we moved suspend handling
> to the clock driver, remove them here.
>
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
>
> ---
>
>  arch/arm/mach-rockchip/pm.h | 7 -------
>  1 file changed, 7 deletions(-)

Reviewed-by: Douglas Anderson <dianders at chromium.org>


From dianders at chromium.org  Mon Jun 22 13:04:02 2015
From: dianders at chromium.org (Doug Anderson)
Date: Mon, 22 Jun 2015 13:04:02 -0700
Subject: [PATCH v2 1/2] ARM: rockchip: add support holding 24Mhz osc
 during suspend
In-Reply-To: <1434880847-29505-2-git-send-email-zyw@rock-chips.com>
References: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
 <1434880847-29505-2-git-send-email-zyw@rock-chips.com>
Message-ID: <CAD=FV=Ux+gKJQtr1Qq+ubTNBKNGKTuCGx-3hTAj0j6fAEEJq2A@mail.gmail.com>

Chris,

On Sun, Jun 21, 2015 at 3:00 AM, Chris Zhong <zyw at rock-chips.com> wrote:
> If we want to wake up system via usb, the 24Mhz osc could not be
> disabled during suspend, read the usb phy SIDDQ bit to decide whether
> to switch to 32khz clock-in.
>
> Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> ---
>
>  arch/arm/mach-rockchip/pm.c | 38 ++++++++++++++++++++++++++++++++++++--
>  1 file changed, 36 insertions(+), 2 deletions(-)

As talked about privately, this patch is ugly.  ...but I don't see a
solution that is less ugly.  This method has the advantages that it is
"automatic"--the system figures out whether it needs the 24MHz clock
automatically based on whether the PHYs were left on.  No other
communication / device tree stuff is needed.


> +       /* if any usb phy is still on(GRF_SIDDQ==0), that means we need the
> +        * function of usb wakeup, so do not switch to 32khz, since the usb phy
> +        * clk does not connect to 32khz osc*/

This is not _quite_ the block commenting style used in this file.  It
would be a bit nicer if it matched.

Other than that:

Reviewed-by: Douglas Anderson <dianders at chromium.org>

On the chromeos-3.14 kernel (with the WIP dwc2 patches):
Tested-by: Douglas Anderson <dianders at chromium.org>


From heiko at sntech.de  Mon Jun 22 14:01:24 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 22 Jun 2015 23:01:24 +0200
Subject: [PATCH v2 1/2] ARM: rockchip: add support holding 24Mhz osc
 during suspend
In-Reply-To: <CAD=FV=Ux+gKJQtr1Qq+ubTNBKNGKTuCGx-3hTAj0j6fAEEJq2A@mail.gmail.com>
References: <1434880847-29505-1-git-send-email-zyw@rock-chips.com>
 <1434880847-29505-2-git-send-email-zyw@rock-chips.com>
 <CAD=FV=Ux+gKJQtr1Qq+ubTNBKNGKTuCGx-3hTAj0j6fAEEJq2A@mail.gmail.com>
Message-ID: <3011002.V7itPuvDk4@diego>

Am Montag, 22. Juni 2015, 13:04:02 schrieb Doug Anderson:
> Chris,
> 
> On Sun, Jun 21, 2015 at 3:00 AM, Chris Zhong <zyw at rock-chips.com> wrote:
> > If we want to wake up system via usb, the 24Mhz osc could not be
> > disabled during suspend, read the usb phy SIDDQ bit to decide whether
> > to switch to 32khz clock-in.
> > 
> > Signed-off-by: Chris Zhong <zyw at rock-chips.com>
> > ---
> > 
> >  arch/arm/mach-rockchip/pm.c | 38 ++++++++++++++++++++++++++++++++++++--
> >  1 file changed, 36 insertions(+), 2 deletions(-)
> 
> As talked about privately, this patch is ugly.  ...but I don't see a
> solution that is less ugly.  This method has the advantages that it is
> "automatic"--the system figures out whether it needs the 24MHz clock
> automatically based on whether the PHYs were left on.  No other
> communication / device tree stuff is needed.

Yep, fully agreed :-) .

As I said before, another possible solution would probably involve checking 
the phy clocks themselfs, but getting these out of the devicetree would make 
this even more ugly.


So I'll let this sit for some more days in case somebody wants to complain 
(middle of the merge window anyway) and apply these two after.


> 
> > +       /* if any usb phy is still on(GRF_SIDDQ==0), that means we need
> > the
> > +        * function of usb wakeup, so do not switch to 32khz, since the
> > usb phy +        * clk does not connect to 32khz osc*/
> 
> This is not _quite_ the block commenting style used in this file.  It
> would be a bit nicer if it matched.
> 
> Other than that:
> 
> Reviewed-by: Douglas Anderson <dianders at chromium.org>
> 
> On the chromeos-3.14 kernel (with the WIP dwc2 patches):
> Tested-by: Douglas Anderson <dianders at chromium.org>



From dianders at chromium.org  Mon Jun 22 16:52:22 2015
From: dianders at chromium.org (Douglas Anderson)
Date: Mon, 22 Jun 2015 16:52:22 -0700
Subject: [PATCH 1/3] USB: Export usb_wakeup_enabled_descendants()
In-Reply-To: <1435017144-2971-1-git-send-email-dianders@chromium.org>
References: <1435017144-2971-1-git-send-email-dianders@chromium.org>
Message-ID: <1435017144-2971-2-git-send-email-dianders@chromium.org>

In (e583d9d USB: global suspend and remote wakeup don't mix) we
introduced wakeup_enabled_descendants() as a static function.  We'd
like to use this function in USB controller drivers to know if we
should keep the controller on during suspend time, since doing so has
a power impact.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/usb/core/hub.c  | 7 ++++---
 include/linux/usb/hcd.h | 5 +++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 43cb2f2..fdc59db 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3034,13 +3034,14 @@ static int usb_disable_remote_wakeup(struct usb_device *udev)
 }
 
 /* Count of wakeup-enabled devices at or below udev */
-static unsigned wakeup_enabled_descendants(struct usb_device *udev)
+unsigned usb_wakeup_enabled_descendants(struct usb_device *udev)
 {
 	struct usb_hub *hub = usb_hub_to_struct_hub(udev);
 
 	return udev->do_remote_wakeup +
 			(hub ? hub->wakeup_enabled_descendants : 0);
 }
+EXPORT_SYMBOL_GPL(usb_wakeup_enabled_descendants);
 
 /*
  * usb_port_suspend - suspend a usb device's upstream port
@@ -3149,7 +3150,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
 	 * Therefore we will turn on the suspend feature if udev or any of its
 	 * descendants is enabled for remote wakeup.
 	 */
-	else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
+	else if (PMSG_IS_AUTO(msg) || usb_wakeup_enabled_descendants(udev) > 0)
 		status = set_port_feature(hub->hdev, port1,
 				USB_PORT_FEAT_SUSPEND);
 	else {
@@ -3548,7 +3549,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 		}
 		if (udev)
 			hub->wakeup_enabled_descendants +=
-					wakeup_enabled_descendants(udev);
+					usb_wakeup_enabled_descendants(udev);
 	}
 
 	if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index c9aa779..30d74c9 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -626,11 +626,16 @@ extern wait_queue_head_t usb_kill_urb_queue;
 #define usb_endpoint_out(ep_dir)	(!((ep_dir) & USB_DIR_IN))
 
 #ifdef CONFIG_PM
+extern unsigned usb_wakeup_enabled_descendants(struct usb_device *udev);
 extern void usb_root_hub_lost_power(struct usb_device *rhdev);
 extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
 extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
 extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
 #else
+static inline unsigned usb_wakeup_enabled_descendants(struct usb_device *udev)
+{
+	return 0;
+}
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
 	return;
-- 
2.4.3.573.g4eafbef



From dianders at chromium.org  Mon Jun 22 16:52:23 2015
From: dianders at chromium.org (Douglas Anderson)
Date: Mon, 22 Jun 2015 16:52:23 -0700
Subject: [PATCH 2/3] Documentation: dt-bindings: Add snps,
 need-phy-for-wake for dwc2 USB
In-Reply-To: <1435017144-2971-1-git-send-email-dianders@chromium.org>
References: <1435017144-2971-1-git-send-email-dianders@chromium.org>
Message-ID: <1435017144-2971-3-git-send-email-dianders@chromium.org>

Some SoCs with a dwc2 USB controller may need to keep the PHY on to
support remote wakeup.  Allow specifying this as a device tree
property.

Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 Documentation/devicetree/bindings/usb/dwc2.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
index fd132cb..84d258d 100644
--- a/Documentation/devicetree/bindings/usb/dwc2.txt
+++ b/Documentation/devicetree/bindings/usb/dwc2.txt
@@ -17,6 +17,9 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties
 Optional properties:
 - phys: phy provider specifier
 - phy-names: shall be "usb2-phy"
+- snps,need-phy-for-wake: if present indicates that the phy needs to be left
+  on for remote wakeup during suspend.
+
 Refer to phy/phy-bindings.txt for generic phy consumer properties
 - dr_mode: shall be one of "host", "peripheral" and "otg"
   Refer to usb/generic.txt
@@ -35,4 +38,5 @@ Example:
 		clock-names = "otg";
 		phys = <&usbphy>;
 		phy-names = "usb2-phy";
+		snps,need-phy-for-wake;
         };
-- 
2.4.3.573.g4eafbef



From dianders at chromium.org  Mon Jun 22 16:52:24 2015
From: dianders at chromium.org (Douglas Anderson)
Date: Mon, 22 Jun 2015 16:52:24 -0700
Subject: [PATCH 3/3] USB: dwc2: Don't turn off the usbphy in suspend if wakeup
 is enabled
In-Reply-To: <1435017144-2971-1-git-send-email-dianders@chromium.org>
References: <1435017144-2971-1-git-send-email-dianders@chromium.org>
Message-ID: <1435017144-2971-4-git-send-email-dianders@chromium.org>

If the 'snps,need-phy-for-wake' is set in the device tree then:

- We know that we can wakeup, so call device_set_wakeup_capable().
  The USB core will use this knowledge to enable wakeup by default.
- We know that we should keep the PHY on during suspend if something
  on our root hub needs remote wakeup.  This requires the patch (USB:
  Export usb_wakeup_enabled_descendants()).  Note that we don't keep
  the PHY on at suspend time if it's not needed because it would be a
  power draw.

If we later find some users of dwc2 that can support wakeup without
keeping the PHY on we may want to add a way to call
device_set_wakeup_capable() without keeping the PHY on at suspend
time.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
Signed-off-by: Douglas Anderson <dianders at chromium.org>
---
 drivers/usb/dwc2/core.h     |  2 ++
 drivers/usb/dwc2/platform.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 53b8de0..b60a1e8 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -687,6 +687,8 @@ struct dwc2_hsotg {
 	enum usb_dr_mode dr_mode;
 	unsigned int hcd_enabled:1;
 	unsigned int gadget_enabled:1;
+	unsigned int need_phy_for_wake:1;
+	unsigned int phy_off_for_suspend:1;
 
 	struct phy *phy;
 	struct usb_phy *uphy;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 9093530..38fce75 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -42,7 +42,9 @@
 #include <linux/of_device.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/usb.h>
 
+#include <linux/usb/hcd.h>
 #include <linux/usb/of.h>
 
 #include "core.h"
@@ -222,6 +224,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
 	hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
 
+	hsotg->need_phy_for_wake =
+		of_property_read_bool(dev->dev.of_node,
+				      "snps,need-phy-for-wake");
+
 	/*
 	 * Attempt to find a generic PHY, then look for an old style
 	 * USB PHY
@@ -265,6 +271,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
 		hsotg->gadget_enabled = 1;
 	}
 
+	/*
+	 * If we need PHY for wakeup we must be wakeup capable.
+	 * When we have a device that can wake without the PHY we
+	 * can adjust this condition.
+	 */
+	if (hsotg->need_phy_for_wake)
+		device_set_wakeup_capable(&dev->dev, true);
+
 	if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
 		retval = dwc2_hcd_init(hsotg, irq);
 		if (retval) {
@@ -282,6 +296,28 @@ static int dwc2_driver_probe(struct platform_device *dev)
 	return retval;
 }
 
+static bool __maybe_unused dwc2_can_poweroff_phy(struct dwc2_hsotg *dwc2)
+{
+	struct usb_device *root_hub = dwc2_hsotg_to_hcd(dwc2)->self.root_hub;
+
+	if (dwc2->lx_state == DWC2_L0)
+		return false;
+
+	/* If the controller isn't allowed to wakeup then we can power off. */
+	if (!device_may_wakeup(dwc2->dev))
+		return true;
+
+	/*
+	 * We don't want to power off the PHY if something under the
+	 * root hub has wakeup enabled.
+	 */
+	if (usb_wakeup_enabled_descendants(root_hub))
+		return false;
+
+	/* No reason to keep the PHY powered, so allow poweroff */
+	return true;
+}
+
 static int __maybe_unused dwc2_suspend(struct device *dev)
 {
 	struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
@@ -290,8 +326,10 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
 	if (dwc2_is_device_mode(dwc2)) {
 		ret = s3c_hsotg_suspend(dwc2);
 	} else {
-		if (dwc2->lx_state == DWC2_L0)
+		if (!dwc2_can_poweroff_phy(dwc2))
 			return 0;
+
+		dwc2->phy_off_for_suspend = true;
 		phy_exit(dwc2->phy);
 		phy_power_off(dwc2->phy);
 
@@ -307,9 +345,12 @@ static int __maybe_unused dwc2_resume(struct device *dev)
 	if (dwc2_is_device_mode(dwc2)) {
 		ret = s3c_hsotg_resume(dwc2);
 	} else {
+		if (!dwc2->phy_off_for_suspend)
+			return ret;
+
 		phy_power_on(dwc2->phy);
 		phy_init(dwc2->phy);
-
+		dwc2->phy_off_for_suspend = false;
 	}
 	return ret;
 }
-- 
2.4.3.573.g4eafbef



From dianders at chromium.org  Mon Jun 22 16:52:21 2015
From: dianders at chromium.org (Douglas Anderson)
Date: Mon, 22 Jun 2015 16:52:21 -0700
Subject: [PATCH 0/3] dwc2 patches to allow wakeup on Rockchip rk3288
Message-ID: <1435017144-2971-1-git-send-email-dianders@chromium.org>

This series of patches, together with
<https://patchwork.kernel.org/patch/6652341/> from Chris Zhong and a
dts change allow us to wake up from a USB device on rk3288 boards.
The patches were tested on rk3288-jerry in the chromeos-3.14 kernel.
The chromeos-3.14 kernel tested included a full set of dwc2 backports
from upstream, so this is expected to function upstream once we get
everything setup there.


Douglas Anderson (3):
  USB: Export usb_wakeup_enabled_descendants()
  Documentation: dt-bindings: Add snps,need-phy-for-wake for dwc2 USB
  USB: dwc2: Don't turn off the usbphy in suspend if wakeup is enabled

 Documentation/devicetree/bindings/usb/dwc2.txt |  4 +++
 drivers/usb/core/hub.c                         |  7 ++--
 drivers/usb/dwc2/core.h                        |  2 ++
 drivers/usb/dwc2/platform.c                    | 45 ++++++++++++++++++++++++--
 include/linux/usb/hcd.h                        |  5 +++
 5 files changed, 58 insertions(+), 5 deletions(-)

-- 
2.4.3.573.g4eafbef



From ykk at rock-chips.com  Mon Jun 22 20:03:22 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Tue, 23 Jun 2015 11:03:22 +0800
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <1434967564.31094.20.camel@x220>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
 <1434967564.31094.20.camel@x220>
Message-ID: <5588CC7A.7060509@rock-chips.com>

Paul,

? 2015/6/22 18:06, Paul Bolle ??:
> Something I didn't notice in v4, sorry.
>
> On Sat, 2015-06-20 at 00:28 +0800, Yakir Yang wrote:
>> --- /dev/null
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c
>> +#define DRIVER_NAME "dw-hdmi-i2s-audio"
>> +MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);
> 0) Side note: this is the first time that PLATFORM_MODULE_PREFIX is used
> inside MODULE_ALIAS(). But none of the 1000+ other "platform:" aliases
> do that. And neither does 5/6 of this series! That suggests, I think,
> that this shouldn't be done.
>
> You could consider adding something like
>      #define MODULE_ALIAS_PLATFORM(NAME) MODULE_ALIAS(PLATFORM_MODULE_PREFIX NAME)
>
> But then, I think, all the current 1000+ platform: aliases should be
> converted to that macro. Would that be worth it?
Yeah, It would be horrible to coverted to that macro   ;)

> 1) Now on to my remark: this alias seems to be only useful if there also
> is a struct platform_device with a "dw-hdmi-i2s-audio" name. Because
> that platform_device would, badly summarized, fire of a
> "MODALIAS=platform:dw-hdmi-i2s-audio" uevent when created. Which, in its
> turn, would trigger userspace to load this module, correct?
>
> But I think there's no platform_device with a "dw-hdmi-i2s-audio" name.
> So I wonder whether this MODULE_ALIAS() is actually needed. What breaks
> if you leave it out?
Thanks for your attentive comment  :).  Actually there should be an 
platform device that named "dw-hdmi-i2s-audio" which I misspelt in 
dw_hdmi.c driver.

thanks,
- Yakir
> (Likewise for 5/6, but there the platform_device should have a
> "rockchip-hdmi-audio" name.)
>
> Thanks,
>
>
> Paul Bolle
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip
>
>
>




From ykk at rock-chips.com  Mon Jun 22 20:06:19 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Tue, 23 Jun 2015 11:06:19 +0800
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <1434967564.31094.20.camel@x220>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
 <1434967564.31094.20.camel@x220>
Message-ID: <5588CD2B.3040807@rock-chips.com>

Paul,

? 2015/6/22 18:06, Paul Bolle ??:
> Something I didn't notice in v4, sorry.
>
> On Sat, 2015-06-20 at 00:28 +0800, Yakir Yang wrote:
>> --- /dev/null
>> +++ b/drivers/gpu/drm/bridge/dw_hdmi-i2s-audio.c
>> +#define DRIVER_NAME "dw-hdmi-i2s-audio"
>> +MODULE_ALIAS(PLATFORM_MODULE_PREFIX DRIVER_NAME);
> 0) Side note: this is the first time that PLATFORM_MODULE_PREFIX is used
> inside MODULE_ALIAS(). But none of the 1000+ other "platform:" aliases
> do that. And neither does 5/6 of this series! That suggests, I think,
> that this shouldn't be done.
>
> You could consider adding something like
>      #define MODULE_ALIAS_PLATFORM(NAME) MODULE_ALIAS(PLATFORM_MODULE_PREFIX NAME)
>
> But then, I think, all the current 1000+ platform: aliases should be
> converted to that macro. Would that be worth it?
Yeah, It would be horrible to coverted to that macro  ;)

> 1) Now on to my remark: this alias seems to be only useful if there also
> is a struct platform_device with a "dw-hdmi-i2s-audio" name. Because
> that platform_device would, badly summarized, fire of a
> "MODALIAS=platform:dw-hdmi-i2s-audio" uevent when created. Which, in its
> turn, would trigger userspace to load this module, correct?
>
> But I think there's no platform_device with a "dw-hdmi-i2s-audio" name.
> So I wonder whether this MODULE_ALIAS() is actually needed. What breaks
> if you leave it out?
Thanks for your attentive comment .  Actually there should be an 
platform device that named "dw-hdmi-i2s-audio" which I misspelt in 
dw_hdmi.c driver.

thanks,
- Yakir

> (Likewise for 5/6, but there the platform_device should have a
> "rockchip-hdmi-audio" name.)
>
> Thanks,
>
>
> Paul Bolle
>
>
>
>




From ykk at rock-chips.com  Mon Jun 22 20:07:59 2015
From: ykk at rock-chips.com (Yakir Yang)
Date: Tue, 23 Jun 2015 11:07:59 +0800
Subject: [PATCH v5 4/6] drm: bridge/dw_hdmi-i2s-audio: add audio driver
In-Reply-To: <20150622101038.GV7557@n2100.arm.linux.org.uk>
References: <1434730417-10629-1-git-send-email-ykk@rock-chips.com>
 <1434731295-11060-1-git-send-email-ykk@rock-chips.com>
 <1434967564.31094.20.camel@x220>
 <20150622101038.GV7557@n2100.arm.linux.org.uk>
Message-ID: <5588CD8F.2040600@rock-chips.com>

Russell,

? 2015/6/22 18:10, Russell King - ARM Linux ??:
> On Mon, Jun 22, 2015 at 12:06:04PM +0200, Paul Bolle wrote:
>> But I think there's no platform_device with a "dw-hdmi-i2s-audio" name.
>> So I wonder whether this MODULE_ALIAS() is actually needed. What breaks
>> if you leave it out?
> +       } else if (hdmi_readb(hdmi, HDMI_CONFIG0_ID) & HDMI_CONFIG0_I2S) {
> +               pdevinfo.name = "dw-hdmi-ahb-audio";
>
> This should be "dw-hdmi-i2s-audio" to avoid picking up on my AHB audio
> driver.
Yep, thanks a lot ;)

- Yakir




From romain.perier at gmail.com  Mon Jun 22 23:53:17 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Tue, 23 Jun 2015 08:53:17 +0200
Subject: [PATCH] ARM: dts: rockchip: Add DMA tx and rx channels in UART
 interfaces for RK3288 SoCs
In-Reply-To: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>
References: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>
Message-ID: <CABgxDo+8MafT8hOzpG=gjju=S7bVtNBOKxmi_JPHv1bDZSGeCQ@mail.gmail.com>

ping :)

2015-06-16 19:19 GMT+02:00 Romain Perier <romain.perier at gmail.com>:
> This enable DMA capability for the corresponding UART interfaces, also it removes
> warning "ttyS%d - Failed to request dma" from kernel logs.
>
> Signed-off-by: Romain Perier <romain.perier at gmail.com>
> ---
>
> Changes since v1 ("[PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for uart2"):
>         - Add DMA tx and rx channels for all UART interfaces
>         - Rename commit summary
>
>  arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
> index 22316d0..1996452 100644
> --- a/arch/arm/boot/dts/rk3288.dtsi
> +++ b/arch/arm/boot/dts/rk3288.dtsi
> @@ -359,6 +359,8 @@
>                 clock-names = "baudclk", "apb_pclk";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&uart0_xfer>;
> +               dmas = <&dmac_peri 1>, <&dmac_peri 2>;
> +               dma-names = "tx", "rx";
>                 status = "disabled";
>         };
>
> @@ -372,6 +374,8 @@
>                 clock-names = "baudclk", "apb_pclk";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&uart1_xfer>;
> +               dmas = <&dmac_peri 3>, <&dmac_peri 4>;
> +               dma-names = "tx", "rx";
>                 status = "disabled";
>         };
>
> @@ -385,6 +389,8 @@
>                 clock-names = "baudclk", "apb_pclk";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&uart2_xfer>;
> +               dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
> +               dma-names = "tx", "rx";
>                 status = "disabled";
>         };
>
> @@ -398,6 +404,8 @@
>                 clock-names = "baudclk", "apb_pclk";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&uart3_xfer>;
> +               dmas = <&dmac_peri 7>, <&dmac_peri 8>;
> +               dma-names = "tx", "rx";
>                 status = "disabled";
>         };
>
> @@ -411,6 +419,8 @@
>                 clock-names = "baudclk", "apb_pclk";
>                 pinctrl-names = "default";
>                 pinctrl-0 = <&uart4_xfer>;
> +               dmas = <&dmac_peri 9>, <&dmac_peri 10>;
> +               dma-names = "tx", "rx";
>                 status = "disabled";
>         };
>
> --
> 1.9.1
>


From heiko at sntech.de  Tue Jun 23 04:09:18 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Tue, 23 Jun 2015 13:09:18 +0200
Subject: [PATCH] ARM: dts: rockchip: Add DMA tx and rx channels in UART
 interfaces for RK3288 SoCs
In-Reply-To: <CABgxDo+8MafT8hOzpG=gjju=S7bVtNBOKxmi_JPHv1bDZSGeCQ@mail.gmail.com>
References: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>
 <CABgxDo+8MafT8hOzpG=gjju=S7bVtNBOKxmi_JPHv1bDZSGeCQ@mail.gmail.com>
Message-ID: <1475991.JRcDMpQrFc@diego>

Hi Romain,

Am Dienstag, 23. Juni 2015, 08:53:17 schrieb Romain Perier:
> ping :)

I haven't forgotten this patch :-)

I just haven't fully made up my mind concerning the bug in the pl330 
implementation on Rockchip SoCs - aka if we'll make it worse by also enabling 
dma on the uarts.

So far the problem reports I read only mentioned degraded functionality like 
popping sounds in audio, not full system failures or freezes. So I tend to 
include the patch and see what happens ;-)


Heiko



> 2015-06-16 19:19 GMT+02:00 Romain Perier <romain.perier at gmail.com>:
> > This enable DMA capability for the corresponding UART interfaces, also it
> > removes warning "ttyS%d - Failed to request dma" from kernel logs.
> > 
> > Signed-off-by: Romain Perier <romain.perier at gmail.com>
> > ---
> > 
> > Changes since v1 ("[PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for 
uart2"):
> >         - Add DMA tx and rx channels for all UART interfaces
> >         - Rename commit summary
> >  
> >  arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
> > index 22316d0..1996452 100644
> > --- a/arch/arm/boot/dts/rk3288.dtsi
> > +++ b/arch/arm/boot/dts/rk3288.dtsi
> > @@ -359,6 +359,8 @@
> > 
> >                 clock-names = "baudclk", "apb_pclk";
> >                 pinctrl-names = "default";
> >                 pinctrl-0 = <&uart0_xfer>;
> > 
> > +               dmas = <&dmac_peri 1>, <&dmac_peri 2>;
> > +               dma-names = "tx", "rx";
> > 
> >                 status = "disabled";
> >         
> >         };
> > 
> > @@ -372,6 +374,8 @@
> > 
> >                 clock-names = "baudclk", "apb_pclk";
> >                 pinctrl-names = "default";
> >                 pinctrl-0 = <&uart1_xfer>;
> > 
> > +               dmas = <&dmac_peri 3>, <&dmac_peri 4>;
> > +               dma-names = "tx", "rx";
> > 
> >                 status = "disabled";
> >         
> >         };
> > 
> > @@ -385,6 +389,8 @@
> > 
> >                 clock-names = "baudclk", "apb_pclk";
> >                 pinctrl-names = "default";
> >                 pinctrl-0 = <&uart2_xfer>;
> > 
> > +               dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
> > +               dma-names = "tx", "rx";
> > 
> >                 status = "disabled";
> >         
> >         };
> > 
> > @@ -398,6 +404,8 @@
> > 
> >                 clock-names = "baudclk", "apb_pclk";
> >                 pinctrl-names = "default";
> >                 pinctrl-0 = <&uart3_xfer>;
> > 
> > +               dmas = <&dmac_peri 7>, <&dmac_peri 8>;
> > +               dma-names = "tx", "rx";
> > 
> >                 status = "disabled";
> >         
> >         };
> > 
> > @@ -411,6 +419,8 @@
> > 
> >                 clock-names = "baudclk", "apb_pclk";
> >                 pinctrl-names = "default";
> >                 pinctrl-0 = <&uart4_xfer>;
> > 
> > +               dmas = <&dmac_peri 9>, <&dmac_peri 10>;
> > +               dma-names = "tx", "rx";
> > 
> >                 status = "disabled";
> >         
> >         };
> > 
> > --
> > 1.9.1



From romain.perier at gmail.com  Tue Jun 23 04:55:52 2015
From: romain.perier at gmail.com (Romain Perier)
Date: Tue, 23 Jun 2015 13:55:52 +0200
Subject: [PATCH] ARM: dts: rockchip: Add DMA tx and rx channels in UART
 interfaces for RK3288 SoCs
In-Reply-To: <1475991.JRcDMpQrFc@diego>
References: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>
 <CABgxDo+8MafT8hOzpG=gjju=S7bVtNBOKxmi_JPHv1bDZSGeCQ@mail.gmail.com>
 <1475991.JRcDMpQrFc@diego>
Message-ID: <CABgxDoJo4=LafA+rf+gN_U=QY0reK3ux8RzHCaYXWfw9FkiLYA@mail.gmail.com>

Hi Heiko,

Oh sure, I completly forgot this issue ^^ , no problem. If you want
some help feel free to ping on IRC.
I did not notice regressions or issues, but my system was not under
load, I will try to investigate and/or test with care.

Have a nice day,
Romain

2015-06-23 13:09 GMT+02:00 Heiko St?bner <heiko at sntech.de>:
> Hi Romain,
>
> Am Dienstag, 23. Juni 2015, 08:53:17 schrieb Romain Perier:
>> ping :)
>
> I haven't forgotten this patch :-)
>
> I just haven't fully made up my mind concerning the bug in the pl330
> implementation on Rockchip SoCs - aka if we'll make it worse by also enabling
> dma on the uarts.
>
> So far the problem reports I read only mentioned degraded functionality like
> popping sounds in audio, not full system failures or freezes. So I tend to
> include the patch and see what happens ;-)
>
>
> Heiko
>
>
>
>> 2015-06-16 19:19 GMT+02:00 Romain Perier <romain.perier at gmail.com>:
>> > This enable DMA capability for the corresponding UART interfaces, also it
>> > removes warning "ttyS%d - Failed to request dma" from kernel logs.
>> >
>> > Signed-off-by: Romain Perier <romain.perier at gmail.com>
>> > ---
>> >
>> > Changes since v1 ("[PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for
> uart2"):
>> >         - Add DMA tx and rx channels for all UART interfaces
>> >         - Rename commit summary
>> >
>> >  arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++
>> >  1 file changed, 10 insertions(+)
>> >
>> > diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
>> > index 22316d0..1996452 100644
>> > --- a/arch/arm/boot/dts/rk3288.dtsi
>> > +++ b/arch/arm/boot/dts/rk3288.dtsi
>> > @@ -359,6 +359,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart0_xfer>;
>> >
>> > +               dmas = <&dmac_peri 1>, <&dmac_peri 2>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -372,6 +374,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart1_xfer>;
>> >
>> > +               dmas = <&dmac_peri 3>, <&dmac_peri 4>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -385,6 +389,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart2_xfer>;
>> >
>> > +               dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -398,6 +404,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart3_xfer>;
>> >
>> > +               dmas = <&dmac_peri 7>, <&dmac_peri 8>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -411,6 +419,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart4_xfer>;
>> >
>> > +               dmas = <&dmac_peri 9>, <&dmac_peri 10>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > --
>> > 1.9.1
>


From zyw at rock-chips.com  Tue Jun 23 05:53:38 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Tue, 23 Jun 2015 20:53:38 +0800
Subject: [PATCH v3 0/2] add support holding 24Mhz osc during suspend
Message-ID: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>

Since the usb-phy clocks are not connected to the 32khz clock-in, they
only have 24Mhz as the clock source. If we want to wake up system via
usb device, we should hold the 24Mhz osc during suspend.
This Patch has tested on chromebook jerry board, with another patch[0],
we can wakeup system via usb keyboard.

[0] https://chromium-review.googlesource.com/#/c/277811/3

Changes in v3:
- Fixed commenting style
- Move the #define-s above the rk3288_slp_disable_osc function

Chris Zhong (2):
  ARM: rockchip: add support holding 24Mhz osc during suspend
  ARM: rockchip: remove some useless macro in pm.h

 arch/arm/mach-rockchip/pm.c | 40 ++++++++++++++++++++++++++++++++++++++--
 arch/arm/mach-rockchip/pm.h |  7 -------
 2 files changed, 38 insertions(+), 9 deletions(-)

-- 
1.9.1



From zyw at rock-chips.com  Tue Jun 23 05:53:39 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Tue, 23 Jun 2015 20:53:39 +0800
Subject: [PATCH v3 1/2] ARM: rockchip: add support holding 24Mhz osc during
 suspend
In-Reply-To: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
References: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1435064020-7057-2-git-send-email-zyw@rock-chips.com>

If we want to wake up system via usb, the 24Mhz osc could not be
disabled during suspend, read the usb phy SIDDQ bit to decide whether
to switch to 32khz clock-in.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>
Tested-by: Douglas Anderson <dianders at chromium.org>

---

Changes in v3:
- Fixed commenting style
- Move the #define-s above the rk3288_slp_disable_osc function

 arch/arm/mach-rockchip/pm.c | 40 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c
index b0dcbe2..9f862c4 100644
--- a/arch/arm/mach-rockchip/pm.c
+++ b/arch/arm/mach-rockchip/pm.c
@@ -45,6 +45,7 @@ static phys_addr_t rk3288_bootram_phy;
 
 static struct regmap *pmu_regmap;
 static struct regmap *sgrf_regmap;
+static struct regmap *grf_regmap;
 
 static u32 rk3288_pmu_pwr_mode_con;
 static u32 rk3288_sgrf_soc_con0;
@@ -66,9 +67,35 @@ static void rk3288_config_bootdata(void)
 	rkpm_bootdata_l2ctlr = rk3288_l2_config();
 }
 
+#define GRF_UOC0_CON0			0x320
+#define GRF_UOC1_CON0			0x334
+#define GRF_UOC2_CON0			0x348
+#define GRF_SIDDQ			BIT(13)
+
+static bool rk3288_slp_disable_osc(void)
+{
+	static const u32 reg_offset[] = { GRF_UOC0_CON0, GRF_UOC1_CON0,
+					  GRF_UOC2_CON0 };
+	u32 reg, i;
+
+	/*
+	 * if any usb phy is still on(GRF_SIDDQ==0), that means we need the
+	 * function of usb wakeup, so do not switch to 32khz, since the usb phy
+	 * clk does not connect to 32khz osc
+	 */
+	for (i = 0; i < ARRAY_SIZE(reg_offset); i++) {
+		regmap_read(grf_regmap, reg_offset[i], &reg);
+		if (!(reg & GRF_SIDDQ))
+			return false;
+	}
+
+	return true;
+}
+
 static void rk3288_slp_mode_set(int level)
 {
 	u32 mode_set, mode_set1;
+	bool osc_switch_to_32k = rk3288_slp_disable_osc();
 
 	regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0);
 
@@ -107,11 +134,13 @@ static void rk3288_slp_mode_set(int level)
 
 	if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) {
 		/* arm off, logic deep sleep */
-		mode_set |= BIT(PMU_BUS_PD_EN) |
+		mode_set |= BIT(PMU_BUS_PD_EN) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) |
-			    BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) |
 			    BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN);
 
+		if (osc_switch_to_32k)
+			mode_set |= BIT(PMU_OSC_24M_DIS);
+
 		mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) |
 			     BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA);
 	} else {
@@ -193,6 +222,13 @@ static int rk3288_suspend_init(struct device_node *np)
 		return PTR_ERR(pmu_regmap);
 	}
 
+	grf_regmap = syscon_regmap_lookup_by_compatible(
+				"rockchip,rk3288-grf");
+	if (IS_ERR(grf_regmap)) {
+		pr_err("%s: could not find grf regmap\n", __func__);
+		return PTR_ERR(pmu_regmap);
+	}
+
 	sram_np = of_find_compatible_node(NULL, NULL,
 					  "rockchip,rk3288-pmu-sram");
 	if (!sram_np) {
-- 
1.9.1



From zyw at rock-chips.com  Tue Jun 23 05:53:40 2015
From: zyw at rock-chips.com (Chris Zhong)
Date: Tue, 23 Jun 2015 20:53:40 +0800
Subject: [PATCH v3 2/2] ARM: rockchip: remove some useless macro in pm.h
In-Reply-To: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
References: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1435064020-7057-3-git-send-email-zyw@rock-chips.com>

These are actually not used in the pm code, as we moved suspend handling
to the clock driver, remove them here.

Signed-off-by: Chris Zhong <zyw at rock-chips.com>
Reviewed-by: Douglas Anderson <dianders at chromium.org>

---

Changes in v3: None

 arch/arm/mach-rockchip/pm.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h
index 3e8d39c..b6494c2 100644
--- a/arch/arm/mach-rockchip/pm.h
+++ b/arch/arm/mach-rockchip/pm.h
@@ -59,13 +59,6 @@ static inline void rockchip_suspend_init(void)
 #define SGRF_DAPDEVICEEN		BIT(0)
 #define SGRF_DAPDEVICEEN_WRITE		BIT(16)
 
-#define RK3288_CRU_MODE_CON		0x50
-#define RK3288_CRU_SEL0_CON		0x60
-#define RK3288_CRU_SEL1_CON		0x64
-#define RK3288_CRU_SEL10_CON		0x88
-#define RK3288_CRU_SEL33_CON		0xe4
-#define RK3288_CRU_SEL37_CON		0xf4
-
 /* PMU_WAKEUP_CFG1 bits */
 #define PMU_ARMINT_WAKEUP_EN		BIT(0)
 
-- 
1.9.1



From davem at davemloft.net  Tue Jun 23 06:49:54 2015
From: davem at davemloft.net (David Miller)
Date: Tue, 23 Jun 2015 06:49:54 -0700 (PDT)
Subject: [PATCH v2 0/4] net: stmmac: dwmac-rk: add support for rk3368
In-Reply-To: <1434916374-7457-1-git-send-email-heiko@sntech.de>
References: <1434916374-7457-1-git-send-email-heiko@sntech.de>
Message-ID: <20150623.064954.1515778425917492486.davem@davemloft.net>

From: Heiko Stuebner <heiko at sntech.de>
Date: Sun, 21 Jun 2015 21:52:50 +0200

> Apart from small cleanups, this series provides support for the dwmac
> on the new rk3368 ARM64 soc.
> 
> Tested on a R88 board using a RMII phy.
> 
> Changes since v1:
> - Adapt to changes resulting from patch d42202dce002 ("net: stmmac:
> dwmac-rk: Don't add function name in info or err messages")

Series applied to net-next, thanks.


From robherring2 at gmail.com  Tue Jun 23 07:17:23 2015
From: robherring2 at gmail.com (Rob Herring)
Date: Tue, 23 Jun 2015 09:17:23 -0500
Subject: [PATCH 2/3] Documentation: dt-bindings: Add snps,
 need-phy-for-wake for dwc2 USB
In-Reply-To: <1435017144-2971-3-git-send-email-dianders@chromium.org>
References: <1435017144-2971-1-git-send-email-dianders@chromium.org>
 <1435017144-2971-3-git-send-email-dianders@chromium.org>
Message-ID: <CAL_JsqJT42GhY45FWY5G=450zxSRVLHu36_O1tPkTdH39JeEcw@mail.gmail.com>

On Mon, Jun 22, 2015 at 6:52 PM, Douglas Anderson <dianders at chromium.org> wrote:
> Some SoCs with a dwc2 USB controller may need to keep the PHY on to
> support remote wakeup.  Allow specifying this as a device tree
> property.

I find it hard to believe that any host can support wake-up without
the PHY. Does this really need to be conditional? Perhaps other cases
are just always-on or remote wake-up has not been tested.

Assuming the PHY was provided with the knowledge that remote wakeup is
enabled, it would be able to figure out within its driver how to
support that. Unfortunately the generic PHY framework is a completely
lacking in its ability to support protocol specific features like this
or other USB PHY features like Vbus detect or charger detection.

Rob

>
> Signed-off-by: Douglas Anderson <dianders at chromium.org>
> ---
>  Documentation/devicetree/bindings/usb/dwc2.txt | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt
> index fd132cb..84d258d 100644
> --- a/Documentation/devicetree/bindings/usb/dwc2.txt
> +++ b/Documentation/devicetree/bindings/usb/dwc2.txt
> @@ -17,6 +17,9 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties
>  Optional properties:
>  - phys: phy provider specifier
>  - phy-names: shall be "usb2-phy"
> +- snps,need-phy-for-wake: if present indicates that the phy needs to be left
> +  on for remote wakeup during suspend.
> +
>  Refer to phy/phy-bindings.txt for generic phy consumer properties
>  - dr_mode: shall be one of "host", "peripheral" and "otg"
>    Refer to usb/generic.txt
> @@ -35,4 +38,5 @@ Example:
>                 clock-names = "otg";
>                 phys = <&usbphy>;
>                 phy-names = "usb2-phy";
> +               snps,need-phy-for-wake;
>          };
> --
> 2.4.3.573.g4eafbef
>


From dianders at chromium.org  Tue Jun 23 08:12:05 2015
From: dianders at chromium.org (Doug Anderson)
Date: Tue, 23 Jun 2015 08:12:05 -0700
Subject: [PATCH 2/3] Documentation: dt-bindings: Add snps,
 need-phy-for-wake for dwc2 USB
In-Reply-To: <CAL_JsqJT42GhY45FWY5G=450zxSRVLHu36_O1tPkTdH39JeEcw@mail.gmail.com>
References: <1435017144-2971-1-git-send-email-dianders@chromium.org>
 <1435017144-2971-3-git-send-email-dianders@chromium.org>
 <CAL_JsqJT42GhY45FWY5G=450zxSRVLHu36_O1tPkTdH39JeEcw@mail.gmail.com>
Message-ID: <CAD=FV=Xpp7GsycBTneJ07vVbh3qaOWtdDVMoS7oh=eqo8CYDrA@mail.gmail.com>

Rob,

On Tue, Jun 23, 2015 at 7:17 AM, Rob Herring <robherring2 at gmail.com> wrote:
> On Mon, Jun 22, 2015 at 6:52 PM, Douglas Anderson <dianders at chromium.org> wrote:
>> Some SoCs with a dwc2 USB controller may need to keep the PHY on to
>> support remote wakeup.  Allow specifying this as a device tree
>> property.
>
> I find it hard to believe that any host can support wake-up without
> the PHY.

I am told by Andrew Bresticker that on tegra there is complicated
logic in the PMU that allows USB wakeup while powering off the PHY.
If I hadn't been aware of such a feature I probably would have called
the property "wakeup-supported" or something like that.

> Does this really need to be conditional? Perhaps other cases
> are just always-on or remote wake-up has not been tested.

When I worked on exynos products I was told by Samsung that USB wakeup
was simply not possible.  True that they have a different USB
controller, but I can certainly believe that someone could design a
system with dwc2 where USB wakeup was not possible.

Specifically, in order to get USB wakeup we had to switch on the 24MHz
clock at suspend time.  Had that not been possible (or had the 24MHz
clock not been able to be a clock source for the USB controller) then
USB wakeup would not be possible on rk3288 even if we left the phy on.

So to me the three states are:
1. USB wake not possible
2. USB wake possible, don't need PHY
3. USB wake possible, do need PHY

I don't know of any dwc2 users that are in #2 (so I didn't add a
property now), but I figure that when they exist someone should add a
property then.


-Doug


From sonnyrao at chromium.org  Tue Jun 23 14:11:36 2015
From: sonnyrao at chromium.org (Sonny Rao)
Date: Tue, 23 Jun 2015 14:11:36 -0700
Subject: [PATCH] ARM: dts: rockchip: Add DMA tx and rx channels in UART
 interfaces for RK3288 SoCs
In-Reply-To: <1475991.JRcDMpQrFc@diego>
References: <1434475166-30338-1-git-send-email-romain.perier@gmail.com>
 <CABgxDo+8MafT8hOzpG=gjju=S7bVtNBOKxmi_JPHv1bDZSGeCQ@mail.gmail.com>
 <1475991.JRcDMpQrFc@diego>
Message-ID: <CAPz6YkUPm+r5BmfxYokJF22yS71VXcsutwKR9y7FiET_3eLpeg@mail.gmail.com>

On Tue, Jun 23, 2015 at 4:09 AM, Heiko St?bner <heiko at sntech.de> wrote:
> Hi Romain,
>
> Am Dienstag, 23. Juni 2015, 08:53:17 schrieb Romain Perier:
>> ping :)
>
> I haven't forgotten this patch :-)
>
> I just haven't fully made up my mind concerning the bug in the pl330
> implementation on Rockchip SoCs - aka if we'll make it worse by also enabling
> dma on the uarts.
>
> So far the problem reports I read only mentioned degraded functionality like
> popping sounds in audio, not full system failures or freezes. So I tend to
> include the patch and see what happens ;-)

You should look out for corrupted data -- like zeros or repeated data
in the serial input or output.  That was what was causing the pops --
a sudden sample of zeros, or buzzing from repeated samples.

It may not happen at low speeds, but might happen if you tried doing
something like PPP over the UART.

>
>
> Heiko
>
>
>
>> 2015-06-16 19:19 GMT+02:00 Romain Perier <romain.perier at gmail.com>:
>> > This enable DMA capability for the corresponding UART interfaces, also it
>> > removes warning "ttyS%d - Failed to request dma" from kernel logs.
>> >
>> > Signed-off-by: Romain Perier <romain.perier at gmail.com>
>> > ---
>> >
>> > Changes since v1 ("[PATCH] ARM: dts: rockchip: Add dmac_bus rx and tx for
> uart2"):
>> >         - Add DMA tx and rx channels for all UART interfaces
>> >         - Rename commit summary
>> >
>> >  arch/arm/boot/dts/rk3288.dtsi | 10 ++++++++++
>> >  1 file changed, 10 insertions(+)
>> >
>> > diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
>> > index 22316d0..1996452 100644
>> > --- a/arch/arm/boot/dts/rk3288.dtsi
>> > +++ b/arch/arm/boot/dts/rk3288.dtsi
>> > @@ -359,6 +359,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart0_xfer>;
>> >
>> > +               dmas = <&dmac_peri 1>, <&dmac_peri 2>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -372,6 +374,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart1_xfer>;
>> >
>> > +               dmas = <&dmac_peri 3>, <&dmac_peri 4>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -385,6 +389,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart2_xfer>;
>> >
>> > +               dmas = <&dmac_bus_s 4>, <&dmac_bus_s 5>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -398,6 +404,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart3_xfer>;
>> >
>> > +               dmas = <&dmac_peri 7>, <&dmac_peri 8>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > @@ -411,6 +419,8 @@
>> >
>> >                 clock-names = "baudclk", "apb_pclk";
>> >                 pinctrl-names = "default";
>> >                 pinctrl-0 = <&uart4_xfer>;
>> >
>> > +               dmas = <&dmac_peri 9>, <&dmac_peri 10>;
>> > +               dma-names = "tx", "rx";
>> >
>> >                 status = "disabled";
>> >
>> >         };
>> >
>> > --
>> > 1.9.1
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


From ulf.hansson at linaro.org  Thu Jun 25 08:33:56 2015
From: ulf.hansson at linaro.org (Ulf Hansson)
Date: Thu, 25 Jun 2015 17:33:56 +0200
Subject: [PATCH v14 2/3] power-domain: rockchip: add power domain driver
In-Reply-To: <557CF1D6.4090506@163.com>
References: <1429862868-14218-1-git-send-email-wxt@rock-chips.com>
 <1429862868-14218-3-git-send-email-wxt@rock-chips.com>
 <CAPDyKFrBzZjOVZzq9unQQwm2BSA0kzeT7EE8_kSpH_udMKjo6A@mail.gmail.com>
 <557CF1D6.4090506@163.com>
Message-ID: <CAPDyKFqa9cQin2HUFuLO_-sSkeASSr08b-3DZ5xGbYHQBPxKag@mail.gmail.com>

[...]

>>> +#include <linux/clk-provider.h>
>>
>> clk-provider.h, why?
>
>
> The following is needed.
>
> _clk_get_name(clk)

I see, you need it for for the dev_dbg().

I think you shall use "%pC" as the formatting string for the dev_dbg()
message, since that will take care of printing the clock name for you.

[...]

>>> +static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool
>>> power_on)
>>> +{
>>> +       int i;
>>> +
>>> +       mutex_lock(&pd->pmu->mutex);
>>
>> I don't quite understand why you need a lock, what are you protecting and
>> why?
>
>
> Says:
> [ 3551.678762] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3551.899180] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3551.905958] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3551.912832] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3551.919730] rockchip_pd_power:139: mutex_lock
> [ 3551.924130] rockchip_pd_power:167,mutex_unlock
> [ 3563.827295] rockchip_pd_power:139: mutex_lock
> [ 3563.831753] rockchip_pd_power:167,mutex_unlock
> [ 3563.836216] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3564.058989] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3564.065659] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3564.072354] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3564.079047] rockchip_pd_power:139: mutex_lock
> [ 3564.083426] rockchip_pd_power:167,mutex_unlock
> [ 3611.665726] rockchip_pd_power:139: mutex_lock
> [ 3611.670206] rockchip_pd_power:167,mutex_unlock
> [ 3611.674692] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3611.899160] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3611.905938] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
> [ 3611.912818] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
> [ 3611.919689] rockchip_pd_power:139: mutex_lock
> [ 3611.924090] rockchip_pd_power:167,mutex_unlock
> [ 3623.848296] rockchip_pd_power:139: mutex_lock
> [ 3623.852752] rockchip_pd_power:167,mutex_unlock
>
>
>
>
>>> +
>>> +       if (rockchip_pmu_domain_is_on(pd) != power_on) {
>>> +               for (i = 0; i < pd->num_clks; i++)
>>> +                       clk_enable(pd->clks[i]);
>>> +
>>> +               if (!power_on) {
>>> +                       /* FIXME: add code to save AXI_QOS */
>>> +
>>> +                       /* if powering down, idle request to NIU first */
>>> +                       rockchip_pmu_set_idle_request(pd, true);
>>> +               }
>>> +
>>> +               rockchip_do_pmu_set_power_domain(pd, power_on);
>>> +
>>> +               if (power_on) {
>>> +                       /* if powering up, leave idle mode */
>>> +                       rockchip_pmu_set_idle_request(pd, false);
>>> +
>>> +                       /* FIXME: add code to restore AXI_QOS */
>>> +               }
>>> +
>>> +               for (i = pd->num_clks - 1; i >= 0; i--)
>>> +                       clk_disable(pd->clks[i]);
>>> +       }
>>> +
>>> +       mutex_unlock(&pd->pmu->mutex);
>>> +       return 0;
>>> +}
>>> +
>>> +static int rockchip_pd_power_on(struct generic_pm_domain *domain)
>>> +{
>>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>>> +
>>> +       return rockchip_pd_power(pd, true);
>>> +}
>>> +
>>> +static int rockchip_pd_power_off(struct generic_pm_domain *domain)
>>> +{
>>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>>> +
>>> +       return rockchip_pd_power(pd, false);
>>> +}
>>> +
>>> +static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
>>> +                                 struct device *dev)
>>> +{
>>> +       struct clk *clk;
>>> +       int i;
>>> +       int error;
>>> +
>>> +       dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
>>> +
>>> +       error = pm_clk_create(dev);
>>> +       if (error) {
>>> +               dev_err(dev, "pm_clk_create failed %d\n", error);
>>> +               return error;
>>> +       }
>>> +
>>> +       i = 0;
>>> +       while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
>>
>> This loop adds all available device clocks to the PM clock list. I
>> wonder if this could be considered as a common thing and if so, we
>> might want to extend the pm_clk API with this.
>
>
> There are several reasons as follows:
>
>     Firstly, the clocks need be turned off to save power when
>     the system enter the suspend state. So we need to enumerate the clocks
>     in the dts. In order to power domain can turn on and off.
>
>     Secondly, the reset-circuit should reset be synchronous on rk3288, then
> sync revoked.
>     So we need to enable clocks of all devices.

I think you misinterpreted my previous answer. Instead of fetching all
clocks for a device and manually create the pm_clk list as you do
here, I was suggesting to make this a part of the pm clk API.

I would happily support such an API, but I can't tell what the other
maintainers think.

>
>>> +               dev_dbg(dev, "adding clock '%s' to list of PM clocks\n",
>>> +                       __clk_get_name(clk));
>>> +               error = pm_clk_add_clk(dev, clk);
>>> +               clk_put(clk);
>>> +               if (error) {
>>> +                       dev_err(dev, "pm_clk_add_clk failed %d\n",
>>> error);
>>> +                       pm_clk_destroy(dev);
>>> +                       return error;
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +

[...]

>>> +
>>> +static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
>>> +                                     struct device_node *node)
>>> +{
>>> +       const struct rockchip_domain_info *pd_info;
>>> +       struct rockchip_pm_domain *pd;
>>> +       struct clk *clk;
>>> +       int clk_cnt;
>>> +       int i;
>>> +       u32 id;
>>> +       int error;
>>> +
>>> +       error = of_property_read_u32(node, "reg", &id);
>>> +       if (error) {
>>> +               dev_err(pmu->dev,
>>> +                       "%s: failed to retrieve domain id (reg): %d\n",
>>> +                       node->name, error);
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       if (id >= pmu->info->num_domains) {
>>> +               dev_err(pmu->dev, "%s: invalid domain id %d\n",
>>> +                       node->name, id);
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       pd_info = &pmu->info->domain_info[id];
>>> +       if (!pd_info) {
>>> +               dev_err(pmu->dev, "%s: undefined domain id %d\n",
>>> +                       node->name, id);
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       clk_cnt = of_count_phandle_with_args(node, "clocks",
>>> "#clock-cells");
>>> +       pd = devm_kzalloc(pmu->dev,
>>> +                         sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
>>> +                         GFP_KERNEL);
>>> +       if (!pd)
>>> +               return -ENOMEM;
>>> +
>>> +       pd->info = pd_info;
>>> +       pd->pmu = pmu;
>>> +
>>> +       for (i = 0; i < clk_cnt; i++) {
>>
>> This loop is similar to the one when creates the PM clock list in the
>> rockchip_pd_attach_dev().
>>
>> What's the reason you don't want to use pm clk for these clocks?
>>
>
> Ditto.

I don't follow. Can't you do the exact same thing via the pm clk API,
can you please elaborate!?

>
>>> +               clk = of_clk_get(node, i);
>>> +               if (IS_ERR(clk)) {
>>> +                       error = PTR_ERR(clk);
>>> +                       dev_err(pmu->dev,
>>> +                               "%s: failed to get clk %s (index %d):
>>> %d\n",
>>> +                               node->name, __clk_get_name(clk), i,
>>> error);
>>> +                       goto err_out;
>>> +               }
>>> +
>>> +               error = clk_prepare(clk);
>>> +               if (error) {
>>> +                       dev_err(pmu->dev,
>>> +                               "%s: failed to prepare clk %s (index %d):
>>> %d\n",
>>> +                               node->name, __clk_get_name(clk), i,
>>> error);
>>> +                       clk_put(clk);
>>> +                       goto err_out;
>>> +               }
>>> +
>>> +               pd->clks[pd->num_clks++] = clk;
>>> +
>>> +               dev_dbg(pmu->dev, "added clock '%s' to domain '%s'\n",
>>> +                       __clk_get_name(clk), node->name);
>>> +       }
>>> +
>>> +       error = rockchip_pd_power(pd, true);
>>> +       if (error) {
>>> +               dev_err(pmu->dev,
>>> +                       "failed to power on domain '%s': %d\n",
>>> +                       node->name, error);
>>> +               goto err_out;
>>> +       }
>>> +
>>> +       pd->genpd.name = node->name;
>>> +       pd->genpd.power_off = rockchip_pd_power_off;
>>> +       pd->genpd.power_on = rockchip_pd_power_on;
>>> +       pd->genpd.attach_dev = rockchip_pd_attach_dev;
>>> +       pd->genpd.detach_dev = rockchip_pd_detach_dev;
>>> +       pd->genpd.dev_ops.start = rockchip_pd_start_dev;
>>> +       pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;
>>
>> Instead of assigning the ->stop|start() callbacks, which do
>> pm_clk_suspend|resume(), just set the genpd->flags to
>> GENPD_FLAG_PM_CLK, and genpd will fix this for you.
>>
> Ditto.

Again, I don't follow. Here is what goes on:

rockchip_pd_start_dev() calls pm_clk_resume() and
rockchip_pd_stop_dev() calls pm_clk_suspend().
Instead of assigning the below callbacks...

pd->genpd.dev_ops.start = rockchip_pd_start_dev;
pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;

... just use GENPD_FLAG_PM_CLK and let genpd deal with the calls to
pm_clk_suspend|resume().

>
>
>>> +       pm_genpd_init(&pd->genpd, NULL, false);
>>> +
>>> +       pmu->genpd_data.domains[id] = &pd->genpd;
>>> +       return 0;
>>> +
>>> +err_out:
>>> +       while (--i >= 0) {
>>> +               clk_unprepare(pd->clks[i]);
>>> +               clk_put(pd->clks[i]);
>>> +       }
>>> +       return error;
>>> +}
>>> +

[...]

Kind regards
Uffe


From heiko at sntech.de  Thu Jun 25 11:12:45 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 25 Jun 2015 20:12:45 +0200
Subject: [PATCH 0/4] arm64: add initial support for the Rockchip rk3368
Message-ID: <1650408.ovnAjReNFJ@diego>

This adds initial support for the new rk3368 ARM64 soc from Rockchip.

Overall it looks like someone dropped some A53 cores into a rk3288, so
it shares a lot of peripherals that only differ in details. Therefore
stuff like the mmc, usb, spi, i2c controllers work out of the box.
The support for the gmac already made it into the merge window as well
as the pinctrl support.

Interestingly, in its core the rk3368 seems trying to be a model student
with psci for smp and using scpi for ddr frequency scaling, although I
currently do not understand how the mailbox works yet. The display
controllers also are only minimally different so I'm hopefully to have
working graphics in the near-ish future :-)


As mentioned in the dts patch, this series depends on the dt-binding
header for the clock ids, so will need a shared branch once this is ready.


Heiko Stuebner (4):
  arm64: add Rockchip architecture entry
  arm64: defconfig: enable ARCH_ROCKCHIP
  arm64: dts: add Rockchip rk3368 core dtsi and board dts for the r88
    board
  dt-bindings: document rk3368 R89 board from Rockchip

 Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
 arch/arm64/Kconfig                                 |  10 +
 arch/arm64/boot/dts/Makefile                       |   1 +
 arch/arm64/boot/dts/rockchip/Makefile              |   5 +
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts        | 353 ++++++++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi           | 900 +++++++++++++++++++++
 arch/arm64/configs/defconfig                       |   2 +
 7 files changed, 1275 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi

-- 
2.1.4




From heiko at sntech.de  Thu Jun 25 11:13:33 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 25 Jun 2015 20:13:33 +0200
Subject: [PATCH 1/4] arm64: add Rockchip architecture entry
In-Reply-To: <1650408.ovnAjReNFJ@diego>
References: <1650408.ovnAjReNFJ@diego>
Message-ID: <1462660.1vQgjvZxuE@diego>

The rk3368 is Rockchip's first ARM64 soc, build around 8 Cortex-A53 cores.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/Kconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 290ed64..9af528a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -197,6 +197,16 @@ config ARCH_QCOM
 	help
 	  This enables support for the ARMv8 based Qualcomm chipsets.
 
+config ARCH_ROCKCHIP
+	bool "Rockchip Platforms"
+	select ARCH_HAS_RESET_CONTROLLER
+	select ARCH_REQUIRE_GPIOLIB
+	select PINCTRL
+	select PINCTRL_ROCKCHIP
+	help
+	  This enables support for the ARMv8 based Rockchip chipsets,
+	  like the RK3368.
+
 config ARCH_SEATTLE
 	bool "AMD Seattle SoC Family"
 	help
-- 
2.1.4




From heiko at sntech.de  Thu Jun 25 11:14:03 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 25 Jun 2015 20:14:03 +0200
Subject: [PATCH 2/4] arm64: defconfig: enable ARCH_ROCKCHIP
In-Reply-To: <1650408.ovnAjReNFJ@diego>
References: <1650408.ovnAjReNFJ@diego>
Message-ID: <1468625.pAhVAPqdrh@diego>

Enable building Rockchip support in the defconfig.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index daefbf0..77bc5bc 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_EXYNOS7=y
 CONFIG_ARCH_FSL_LS2085A=y
 CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_TEGRA_132_SOC=y
@@ -99,6 +100,7 @@ CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-- 
2.1.4




From heiko at sntech.de  Thu Jun 25 11:14:38 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 25 Jun 2015 20:14:38 +0200
Subject: [PATCH 3/4] arm64: dts: add Rockchip rk3368 core dtsi and board dts
 for the r88 board
In-Reply-To: <1650408.ovnAjReNFJ@diego>
References: <1650408.ovnAjReNFJ@diego>
Message-ID: <3220645.At1oVfRcjk@diego>

In terms of peripherals the rk3368 is quite similar to the rk3288, which
makes it possible to have a lot basic components working in the first go.
More to follow once I tracked down all the tiny differences that still
exist in some parts.

With these dts files, the R88 board is able to boot from an attached
usb device and most likely from its emmc too, if the emmc uses a standard
partition table instead of Rockchip's own one - the emmc itself is
detected correctly.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
This of course needs the dt-binding header from clock series, so
a shared branch will be needed.

 arch/arm64/boot/dts/Makefile                |   1 +
 arch/arm64/boot/dts/rockchip/Makefile       |   5 +
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 353 +++++++++++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi    | 900 ++++++++++++++++++++++++++++
 4 files changed, 1259 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index ad26a75..6916eec 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -6,6 +6,7 @@ dts-dirs += exynos
 dts-dirs += freescale
 dts-dirs += mediatek
 dts-dirs += qcom
+dts-dirs += rockchip
 dts-dirs += sprd
 dts-dirs += xilinx
 
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
new file mode 100644
index 0000000..601e6a2
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
new file mode 100644
index 0000000..d0c519b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+
+/ {
+	model = "Rockchip R88";
+	compatible = "rockchip,r88", "rockchip,rk3368";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory {
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		pinctrl-0 = <&emmc_reset>;
+		pinctrl-names = "default";
+		reset-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+	};
+
+	keys: gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_key>;
+
+		button at 0 {
+			gpio-key,wakeup = <1>;
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			label = "GPIO Power";
+			linux,code = <116>;
+		};
+	};
+
+	leds: gpio-leds {
+		compatible = "gpio-leds";
+
+		work {
+			gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+			label = "r88:green:led";
+			pinctrl-names = "default";
+			pinctrl-0 = <&led_ctl>;
+		};
+	};
+
+	ir: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_int>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&hym8563>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bt_rst>, <&wifi_reg_on>;
+
+		reset-gpios =
+			/* BT_RST_N */
+			<&gpio3 5 GPIO_ACTIVE_LOW>,
+
+			/* WL_REG_ON */
+			<&gpio3 4 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc_18: vcc18-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_18";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	/* supplies both host and otg */
+	vcc_host: vcc-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc_host";
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_io: vcc-io-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_lan: vcc-lan-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_lan";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vccio_wl: vccio-wl-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vccio_wl";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_io>;
+	};
+
+	vdd_10: vdd-10-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_10";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+};
+
+&emmc {
+	broken-cd;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	mmc-pwrseq = <&emmc_pwrseq>;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+	status = "okay";
+};
+
+&gmac {
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rmii";
+	clock_in_out = "output";
+	snps,reset-gpio = <&gpio3 12 0>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rmii_pins>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "ok";
+};
+
+&i2c0 {
+	status = "okay";
+
+	vdd_cpu: syr827 at 40 {
+		compatible = "silergy,syr827";
+		reg = <0x40>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-name = "vdd_cpu";
+		regulator-enable-ramp-delay = <300>;
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <8000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	hym8563: hym8563 at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+		/* rtc_int is not connected */
+	};
+};
+
+&sdio0 {
+	assigned-clocks = <&cru SCLK_SDIO0>;
+	assigned-clock-parents = <&cru PLL_CPLL>;
+	broken-cd;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cap-sdio-irq;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_clk &sdio0_cmd &sdio0_bus4>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vccio_wl>;
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+		bias-disable;
+		drive-strength = <8>;
+	};
+
+	pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+		bias-pull-up;
+		drive-strength = <8>;
+	};
+
+	emmc {
+		emmc_bus8: emmc-bus8 {
+			rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+		};
+
+		emmc-clk {
+			rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+		};
+
+		emmc-cmd {
+			rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+		};
+
+		emmc_reset: emmc-reset {
+			rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	ir {
+		ir_int: ir-int {
+			rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	keys {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	leds {
+		stby_pwren: stby-pwren {
+			rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		led_ctl: led-ctl {
+			rockchip,pins = <3 29 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdio {
+		wifi_reg_on: wifi-reg-on {
+			rockchip,pins = <3 4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_rst: bt-rst {
+			rockchip,pins = <3 5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&saradc {
+	vref-supply = <&vcc_18>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
new file mode 100644
index 0000000..a712bea
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -0,0 +1,900 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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 library 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 library 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.
+ */
+
+#include <dt-bindings/clock/rk3368-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+/ {
+	compatible = "rockchip,rk3368";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu_b0>;
+				};
+				core1 {
+					cpu = <&cpu_b1>;
+				};
+				core2 {
+					cpu = <&cpu_b2>;
+				};
+				core3 {
+					cpu = <&cpu_b3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu_l0>;
+				};
+				core1 {
+					cpu = <&cpu_l1>;
+				};
+				core2 {
+					cpu = <&cpu_l2>;
+				};
+				core3 {
+					cpu = <&cpu_l3>;
+				};
+			};
+		};
+
+		idle-states {
+			entry-method = "arm,psci";
+
+			cpu_sleep: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x1010000>;
+				entry-latency-us = <0x3fffffff>;
+				exit-latency-us = <0x40000000>;
+				min-residency-us = <0xffffffff>;
+			};
+		};
+
+		cpu_l0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b0: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x100>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b1: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x101>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b2: cpu at 102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x102>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b3: cpu at 103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x103>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu_l0>, <&cpu_l1>, <&cpu_l2>,
+				     <&cpu_l3>, <&cpu_b0>, <&cpu_b1>,
+				     <&cpu_b2>, <&cpu_b3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	sdmmc: dwmmc at ff0c0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0c0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	sdio0: dwmmc at ff0d0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0d0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
+			 <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	emmc: dwmmc at ff0f0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0f0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	saradc: saradc at ff100000 {
+		compatible = "rockchip,saradc";
+		reg = <0x0 0xff100000 0x0 0x100>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		status = "disabled";
+	};
+
+	spi0: spi at ff110000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff110000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi at ff120000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff120000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi2: spi at ff130000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff130000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c at ff140000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		status = "disabled";
+	};
+
+	i2c3: i2c at ff150000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff150000 0x0 0x1000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		status = "disabled";
+	};
+
+	i2c4: i2c at ff160000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff160000 0x0 0x1000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_xfer>;
+		status = "disabled";
+	};
+
+	i2c5: i2c at ff170000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff170000 0x0 0x1000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C5>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_xfer>;
+		status = "disabled";
+	};
+
+	uart0: serial at ff180000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff180000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart1: serial at ff190000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff190000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart3: serial at ff1b0000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1b0000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart4: serial at ff1c0000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1c0000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	gmac: ethernet at ff290000 {
+		compatible = "rockchip,rk3368-gmac";
+		reg = <0x0 0xff290000 0x0 0x10000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "macirq";
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_MAC>,
+			<&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>,
+			<&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>,
+			<&cru ACLK_GMAC>, <&cru PCLK_GMAC>;
+		clock-names = "stmmaceth",
+			"mac_clk_rx", "mac_clk_tx",
+			"clk_mac_ref", "clk_mac_refout",
+			"aclk_mac", "pclk_mac";
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb at ff500000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xff500000 0x0 0x100>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>;
+		clock-names = "usbhost";
+		status = "disabled";
+	};
+
+	usb_otg: usb at ff580000 {
+		compatible = "rockchip,rk3368-usb", "rockchip,rk3066-usb",
+				"snps,dwc2";
+		reg = <0x0 0xff580000 0x0 0x40000>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_OTG0>;
+		clock-names = "otg";
+		dr_mode = "otg";
+		g-np-tx-fifo-size = <16>;
+		g-rx-fifo-size = <275>;
+		g-tx-fifo-size = <256 128 128 64 64 32>;
+		g-use-dma;
+		status = "disabled";
+	};
+
+	i2c0: i2c at ff650000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff650000 0x0 0x1000>;
+		clocks = <&cru PCLK_I2C0>;
+		clock-names = "i2c";
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c at ff660000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff660000 0x0 0x1000>;
+		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		status = "disabled";
+	};
+
+	uart2: serial at ff690000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff690000 0x0 0x100>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_xfer>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	pmugrf: syscon at ff738000 {
+		compatible = "rockchip,rk3368-pmugrf", "syscon";
+		reg = <0x0 0xff738000 0x0 0x1000>;
+	};
+
+	cru: clock-controller at ff760000 {
+		compatible = "rockchip,rk3368-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	grf: syscon at ff770000 {
+		compatible = "rockchip,rk3368-grf", "syscon";
+		reg = <0x0 0xff770000 0x0 0x1000>;
+	};
+
+	wdt: watchdog at ff800000 {
+		compatible = "rockchip,rk3368-wdt", "snps,dw-wdt";
+		reg = <0x0 0xff800000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller at ffb71000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0x0 0xffb71000 0x0 0x1000>,
+		      <0x0 0xffb72000 0x0 0x1000>,
+		      <0x0 0xffb74000 0x0 0x2000>,
+		      <0x0 0xffb76000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9
+		      (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3368-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <0x2>;
+		#size-cells = <0x2>;
+		ranges;
+
+		gpio0: gpio0 at ff750000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff750000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO0>;
+			interrupts = <GIC_SPI 0x51 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio1: gpio1 at ff780000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff780000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO1>;
+			interrupts = <GIC_SPI 0x52 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio2: gpio2 at ff790000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff790000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO2>;
+			interrupts = <GIC_SPI 0x53 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio3: gpio3 at ff7a0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff7a0000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO3>;
+			interrupts = <GIC_SPI 0x54 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_pwr: emmc-pwr {
+				rockchip,pins = <1 27 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus4: emmc-bus4 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
+						<1 19 RK_FUNC_2 &pcfg_pull_up>,
+						<1 20 RK_FUNC_2 &pcfg_pull_up>,
+						<1 21 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
+						<1 19 RK_FUNC_2 &pcfg_pull_up>,
+						<1 20 RK_FUNC_2 &pcfg_pull_up>,
+						<1 21 RK_FUNC_2 &pcfg_pull_up>,
+						<1 22 RK_FUNC_2 &pcfg_pull_up>,
+						<1 23 RK_FUNC_2 &pcfg_pull_up>,
+						<1 24 RK_FUNC_2 &pcfg_pull_up>,
+						<1 25 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		gmac {
+			rgmii_pins: rgmii-pins {
+				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
+						<3 24 RK_FUNC_1 &pcfg_pull_none>,
+						<3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 10 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 14 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 28 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 15 RK_FUNC_1 &pcfg_pull_none>,
+						<3 16 RK_FUNC_1 &pcfg_pull_none>,
+						<3 17 RK_FUNC_1 &pcfg_pull_none>,
+						<3 18 RK_FUNC_1 &pcfg_pull_none>,
+						<3 25 RK_FUNC_1 &pcfg_pull_none>,
+						<3 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			rmii_pins: rmii-pins {
+				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
+						<3 24 RK_FUNC_1 &pcfg_pull_none>,
+						<3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 15 RK_FUNC_1 &pcfg_pull_none>,
+						<3 16 RK_FUNC_1 &pcfg_pull_none>,
+						<3 20 RK_FUNC_1 &pcfg_pull_none>,
+						<3 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
+						<0 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <2 21 RK_FUNC_1 &pcfg_pull_none>,
+						<2 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <0 9 RK_FUNC_2 &pcfg_pull_none>,
+						<3 31 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>,
+						<1 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <3 24 RK_FUNC_2 &pcfg_pull_none>,
+						<3 25 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c5 {
+			i2c5_xfer: i2c5-xfer {
+				rockchip,pins = <3 26 RK_FUNC_2 &pcfg_pull_none>,
+						<3 27 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		sdio0 {
+			sdio0_bus1: sdio0-bus1 {
+				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bus4: sdio0-bus4 {
+				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>,
+						<2 29 RK_FUNC_1 &pcfg_pull_up>,
+						<2 30 RK_FUNC_1 &pcfg_pull_up>,
+						<2 31 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_cmd: sdio0-cmd {
+				rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_clk: sdio0-clk {
+				rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdio0_cd: sdio0-cd {
+				rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_wp: sdio0-wp {
+				rockchip,pins = <3 3 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_pwr: sdio0-pwr {
+				rockchip,pins = <3 4 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bkpwr: sdio0-bkpwr {
+				rockchip,pins = <3 5 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_int: sdio0-int {
+				rockchip,pins = <3 6 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_cd: sdmcc-cd {
+				rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>,
+						<2 6 RK_FUNC_1 &pcfg_pull_up>,
+						<2 7 RK_FUNC_1 &pcfg_pull_up>,
+						<2 8 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins = <1 29 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins = <1 24 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins = <1 25 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins = <1 23 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins = <1 22 RK_FUNC_3 &pcfg_pull_up>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins = <1 14 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins = <1 15 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs1: spi1-cs1 {
+				rockchip,pins = <3 28 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins = <1 16 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins = <1 17 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi2 {
+			spi2_clk: spi2-clk {
+				rockchip,pins = <0 12 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_cs0: spi2-cs0 {
+				rockchip,pins = <0 13 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_rx: spi2-rx {
+				rockchip,pins = <0 10 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_tx: spi2-tx {
+				rockchip,pins = <0 11 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <2 24 RK_FUNC_1 &pcfg_pull_up>,
+						<2 25 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <2 27 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <0 20 RK_FUNC_3 &pcfg_pull_up>,
+						<0 21 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <0 22 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <0 23 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <2 6 RK_FUNC_2 &pcfg_pull_up>,
+						<2 5 RK_FUNC_2 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart2 */
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <3 29 RK_FUNC_2 &pcfg_pull_up>,
+						<3 30 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins = <3 17 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins = <0 27 RK_FUNC_3 &pcfg_pull_up>,
+						<0 26 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart4_cts: uart4-cts {
+				rockchip,pins = <0 24 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart4_rts: uart4-rts {
+				rockchip,pins = <0 25 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+	};
+};
-- 
2.1.4




From heiko at sntech.de  Thu Jun 25 11:15:12 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Thu, 25 Jun 2015 20:15:12 +0200
Subject: [PATCH 4/4] dt-bindings: document rk3368 R89 board from Rockchip
In-Reply-To: <1650408.ovnAjReNFJ@diego>
References: <1650408.ovnAjReNFJ@diego>
Message-ID: <1656103.SqN7hZrCiS@diego>

The initial board containing the rk3368 ARM64 soc.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
This should probably be simply in one branch with the Netxeon board
seen in the diff above, to prevent unncessary merge conflicts?

 Documentation/devicetree/bindings/arm/rockchip.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index b30bed1..c4119e0 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -30,3 +30,7 @@ Rockchip platforms device tree bindings
 - Netxeon R89 board:
     Required root node properties:
       - compatible = "netxeon,r89", "rockchip,rk3288";
+
+- Rockchip R88 board:
+    Required root node properties:
+      - compatible = "rockchip,r88", "rockchip,rk3368";
-- 
2.1.4




From mark.yao at rock-chips.com  Thu Jun 25 18:27:18 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 09:27:18 +0800
Subject: [PATCH v2] drm/rockchip: import dma_buf to gem
Message-ID: <1435282038-23778-1-git-send-email-mark.yao@rock-chips.com>

We want to display a buffer allocated by other driver, need import
the buffer to gem.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
Changes in v2:
Adviced by Russell King
- check sgt-nents == 1 when get iova from scatterlist
- remove unused dma_map_sg/dma_unmap_sg, dma_buf_map_attachment->map_dma_buf
  should do the dma_map

 drivers/gpu/drm/rockchip/rockchip_drm_drv.c |    1 +
 drivers/gpu/drm/rockchip/rockchip_drm_gem.c |   40 +++++++++++++++++++++++++--
 drivers/gpu/drm/rockchip/rockchip_drm_gem.h |    5 +++-
 3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 3962176..9001a90 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -287,6 +287,7 @@ static struct drm_driver rockchip_drm_driver = {
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
 	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table,
 	.gem_prime_export	= drm_gem_prime_export,
 	.gem_prime_get_sg_table	= rockchip_gem_prime_get_sg_table,
 	.gem_prime_vmap		= rockchip_gem_prime_vmap,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index eb2282c..e8c4d4e 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -18,6 +18,7 @@
 #include <drm/drm_vma_manager.h>
 
 #include <linux/dma-attrs.h>
+#include <linux/dma-buf.h>
 
 #include "rockchip_drm_drv.h"
 #include "rockchip_drm_gem.h"
@@ -105,6 +106,36 @@ int rockchip_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 	return ret;
 }
 
+struct drm_gem_object *
+rockchip_gem_prime_import_sg_table(struct drm_device *drm,
+				   struct dma_buf_attachment *attach,
+				   struct sg_table *sgt)
+{
+	struct rockchip_gem_object *rk_obj;
+	struct drm_gem_object *obj;
+
+	/*
+	 * Todo: only support continuous buffer now, plan to found a method
+	 * to import non continuous with iommu.
+	 */
+	if (sgt->nents != 1)
+		return ERR_PTR(-EINVAL);
+
+	rk_obj = kzalloc(sizeof(*rk_obj), GFP_KERNEL);
+	if (!rk_obj)
+		return ERR_PTR(-ENOMEM);
+
+	obj = &rk_obj->base;
+
+	drm_gem_private_object_init(drm, obj, attach->dmabuf->size);
+
+	rk_obj->dma_addr = sg_dma_address(sgt->sgl);
+	rk_obj->sgt = sgt;
+	obj->size = sg_dma_len(sgt->sgl);
+
+	return obj;
+}
+
 struct rockchip_gem_object *
 	rockchip_gem_create_object(struct drm_device *drm, unsigned int size,
 				   bool alloc_kmap)
@@ -142,11 +173,14 @@ void rockchip_gem_free_object(struct drm_gem_object *obj)
 {
 	struct rockchip_gem_object *rk_obj;
 
-	drm_gem_free_mmap_offset(obj);
-
 	rk_obj = to_rockchip_obj(obj);
 
-	rockchip_gem_free_buf(rk_obj);
+	if (obj->import_attach) {
+		drm_prime_gem_destroy(obj, rk_obj->sgt);
+	} else {
+		drm_gem_free_mmap_offset(obj);
+		rockchip_gem_free_buf(rk_obj);
+	}
 
 	kfree(rk_obj);
 }
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index ad22618..9fd58e3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -21,6 +21,7 @@ struct rockchip_gem_object {
 	struct drm_gem_object base;
 	unsigned int flags;
 
+	struct sg_table *sgt;
 	void *kvaddr;
 	dma_addr_t dma_addr;
 	struct dma_attrs dma_attrs;
@@ -28,8 +29,10 @@ struct rockchip_gem_object {
 
 struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj);
 struct drm_gem_object *
-rockchip_gem_prime_import_sg_table(struct drm_device *dev, size_t size,
+rockchip_gem_prime_import_sg_table(struct drm_device *drm,
+				   struct dma_buf_attachment *attach,
 				   struct sg_table *sgt);
+
 void *rockchip_gem_prime_vmap(struct drm_gem_object *obj);
 void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 
-- 
1.7.9.5




From bamv2005 at gmail.com  Thu Jun 25 21:35:58 2015
From: bamv2005 at gmail.com (Bamvor Jian Zhang)
Date: Fri, 26 Jun 2015 12:35:58 +0800
Subject: [PATCH 0/4] arm64: add initial support for the Rockchip rk3368
In-Reply-To: <1650408.ovnAjReNFJ@diego>
References: <1650408.ovnAjReNFJ@diego>
Message-ID: <558CD6AE.7030505@gmail.com>

Hi, Heiko

Could I test the code on rk3368 STB such as EKB368, CSA90?
Is there some documents about it?

Thanks

bamvor	

On 06/26/2015 02:12 AM, Heiko St?bner wrote:
> This adds initial support for the new rk3368 ARM64 soc from Rockchip.
>
> Overall it looks like someone dropped some A53 cores into a rk3288, so
> it shares a lot of peripherals that only differ in details. Therefore
> stuff like the mmc, usb, spi, i2c controllers work out of the box.
> The support for the gmac already made it into the merge window as well
> as the pinctrl support.
>
> Interestingly, in its core the rk3368 seems trying to be a model student
> with psci for smp and using scpi for ddr frequency scaling, although I
> currently do not understand how the mailbox works yet. The display
> controllers also are only minimally different so I'm hopefully to have
> working graphics in the near-ish future :-)
>
>
> As mentioned in the dts patch, this series depends on the dt-binding
> header for the clock ids, so will need a shared branch once this is ready.
>
>
> Heiko Stuebner (4):
>    arm64: add Rockchip architecture entry
>    arm64: defconfig: enable ARCH_ROCKCHIP
>    arm64: dts: add Rockchip rk3368 core dtsi and board dts for the r88
>      board
>    dt-bindings: document rk3368 R89 board from Rockchip
>
>   Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
>   arch/arm64/Kconfig                                 |  10 +
>   arch/arm64/boot/dts/Makefile                       |   1 +
>   arch/arm64/boot/dts/rockchip/Makefile              |   5 +
>   arch/arm64/boot/dts/rockchip/rk3368-r88.dts        | 353 ++++++++
>   arch/arm64/boot/dts/rockchip/rk3368.dtsi           | 900 +++++++++++++++++++++
>   arch/arm64/configs/defconfig                       |   2 +
>   7 files changed, 1275 insertions(+)
>   create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
>   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
>   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi
>


From heiko at sntech.de  Fri Jun 26 00:17:25 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 26 Jun 2015 09:17:25 +0200
Subject: [PATCH 0/4] arm64: add initial support for the Rockchip rk3368
In-Reply-To: <558CD6AE.7030505@gmail.com>
References: <1650408.ovnAjReNFJ@diego> <558CD6AE.7030505@gmail.com>
Message-ID: <2154359.YLevLOlh2Y@diego>

Hi Bamvor,

Am Freitag, 26. Juni 2015, 12:35:58 schrieb Bamvor Jian Zhang:
> Could I test the code on rk3368 STB such as EKB368, CSA90?
> Is there some documents about it?

General information on flashing generic Rockchip devices can be found on [0]. 
That didn't change for the rk3368 it seems - although a device _might_ be 
locked down to prevent reflashing it seems.

You will of course also need a serial console on the device for the time 
being, so finding the test-points and soldering is probably required.


Heiko


[0] http://linux-rockchip.info


> On 06/26/2015 02:12 AM, Heiko St?bner wrote:
> > This adds initial support for the new rk3368 ARM64 soc from Rockchip.
> > 
> > Overall it looks like someone dropped some A53 cores into a rk3288, so
> > it shares a lot of peripherals that only differ in details. Therefore
> > stuff like the mmc, usb, spi, i2c controllers work out of the box.
> > The support for the gmac already made it into the merge window as well
> > as the pinctrl support.
> > 
> > Interestingly, in its core the rk3368 seems trying to be a model student
> > with psci for smp and using scpi for ddr frequency scaling, although I
> > currently do not understand how the mailbox works yet. The display
> > controllers also are only minimally different so I'm hopefully to have
> > working graphics in the near-ish future :-)
> > 
> > 
> > As mentioned in the dts patch, this series depends on the dt-binding
> > header for the clock ids, so will need a shared branch once this is ready.
> > 
> > Heiko Stuebner (4):
> >    arm64: add Rockchip architecture entry
> >    arm64: defconfig: enable ARCH_ROCKCHIP
> >    arm64: dts: add Rockchip rk3368 core dtsi and board dts for the r88
> >    
> >      board
> >    
> >    dt-bindings: document rk3368 R89 board from Rockchip
> >   
> >   Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
> >   arch/arm64/Kconfig                                 |  10 +
> >   arch/arm64/boot/dts/Makefile                       |   1 +
> >   arch/arm64/boot/dts/rockchip/Makefile              |   5 +
> >   arch/arm64/boot/dts/rockchip/rk3368-r88.dts        | 353 ++++++++
> >   arch/arm64/boot/dts/rockchip/rk3368.dtsi           | 900
> >   +++++++++++++++++++++ arch/arm64/configs/defconfig                     
> >    |   2 +
> >   7 files changed, 1275 insertions(+)
> >   create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
> >   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
> >   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi



From heiko at sntech.de  Fri Jun 26 02:13:47 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Fri, 26 Jun 2015 11:13:47 +0200
Subject: [PATCH v3 0/2] add support holding 24Mhz osc during suspend
In-Reply-To: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
References: <1435064020-7057-1-git-send-email-zyw@rock-chips.com>
Message-ID: <1819327.FqTWPKx08f@diego>

Am Dienstag, 23. Juni 2015, 20:53:38 schrieb Chris Zhong:
> Since the usb-phy clocks are not connected to the 32khz clock-in, they
> only have 24Mhz as the clock source. If we want to wake up system via
> usb device, we should hold the 24Mhz osc during suspend.
> This Patch has tested on chromebook jerry board, with another patch[0],
> we can wakeup system via usb keyboard.
> 
> [0] https://chromium-review.googlesource.com/#/c/277811/3

applied both to my soc branch for 4.3


From mark.rutland at arm.com  Fri Jun 26 02:34:01 2015
From: mark.rutland at arm.com (Mark Rutland)
Date: Fri, 26 Jun 2015 10:34:01 +0100
Subject: [PATCH 3/4] arm64: dts: add Rockchip rk3368 core dtsi and board
 dts for the r88 board
In-Reply-To: <3220645.At1oVfRcjk@diego>
References: <1650408.ovnAjReNFJ@diego>
 <3220645.At1oVfRcjk@diego>
Message-ID: <20150626093400.GA19947@leverpostej>

[...]

> +       memory {
> +               reg = <0x0 0x0 0x0 0x40000000>;
> +       };

This needs device_type = "memory", no?

I guess the bootloader is overriding this anyway?

Otherwise this looked fine to me.

Thanks,
Mark.


From mark.yao at rock-chips.com  Fri Jun 26 03:07:24 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:07:24 +0800
Subject: [PATCH v2 0/5] drm/rockchip: support yuv overlay and plane scale
Message-ID: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>

This series patches are used for yuv image overlay display.

Rockchip vop support NV11, NV16, NV24 yuv format,
and can scale the image scale 1/8 to 8.

Changes in v2:
- Uv buffer not support odd offset, align it.
- Fix error display when move yuv image. 
- Fix scale dest info. 

Mark Yao (5):
  drm/rockchip: vop: optimize virtual stride calculate
  drm/rockchip: vop: fix yuv plane support
  drm/rockchip: vop: support plane scale
  drm/rockchip: vop: switch cursor plane to window 3
  drm/rockchip: default enable win2/3 area0 bit

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  467 ++++++++++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   96 ++++++
 2 files changed, 551 insertions(+), 12 deletions(-)

-- 
1.7.9.5




From mark.yao at rock-chips.com  Fri Jun 26 03:07:25 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:07:25 +0800
Subject: [PATCH v2 1/5] drm/rockchip: vop: optimize virtual stride calculate
In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1435313249-4549-2-git-send-email-mark.yao@rock-chips.com>

vir_stride need number words of the virtual width, and fb->pitches
save bytes_per_pixel, so just div 4 switch to stride.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 6188221..3c9f4f3 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -644,7 +644,7 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	offset += (src.y1 >> 16) * fb->pitches[0];
 	yrgb_mst = rk_obj->dma_addr + offset;
 
-	y_vir_stride = fb->pitches[0] / (fb->bits_per_pixel >> 3);
+	y_vir_stride = fb->pitches[0] >> 2;
 
 	/*
 	 * If this plane update changes the plane's framebuffer, (or more
-- 
1.7.9.5




From mark.yao at rock-chips.com  Fri Jun 26 03:07:26 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:07:26 +0800
Subject: [PATCH v2 2/5] drm/rockchip: vop: fix yuv plane support
In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1435313249-4549-3-git-send-email-mark.yao@rock-chips.com>

vop support yuv with NV12, NV16 and NV24, only 2 plane yuv.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>

Changes in v2:
- Uv buffer not support odd offset, align it.
- Fix error display when move yuv image.  

---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |   63 ++++++++++++++++++++++++---
 1 file changed, 57 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 3c9f4f3..6ca08f8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -373,6 +373,18 @@ static enum vop_data_format vop_convert_format(uint32_t format)
 	}
 }
 
+static bool is_yuv_support(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static bool is_alpha_support(uint32_t format)
 {
 	switch (format) {
@@ -577,16 +589,21 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	struct vop *vop = to_vop(crtc);
 	struct drm_gem_object *obj;
 	struct rockchip_gem_object *rk_obj;
+	struct drm_gem_object *uv_obj;
+	struct rockchip_gem_object *rk_uv_obj;
 	unsigned long offset;
 	unsigned int actual_w;
 	unsigned int actual_h;
 	unsigned int dsp_stx;
 	unsigned int dsp_sty;
 	unsigned int y_vir_stride;
+	unsigned int uv_vir_stride;
 	dma_addr_t yrgb_mst;
+	dma_addr_t uv_mst;
 	enum vop_data_format format;
 	uint32_t val;
 	bool is_alpha;
+	bool is_yuv;
 	bool visible;
 	int ret;
 	struct drm_rect dest = {
@@ -608,6 +625,12 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	};
 	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
 
+	if (drm_format_num_planes(fb->pixel_format) > 2) {
+		DRM_ERROR("unsupport more than 2 plane format[%08x]\n",
+			  fb->pixel_format);
+		return -EINVAL;
+	}
+
 	ret = drm_plane_helper_check_update(plane, crtc, fb,
 					    &src, &dest, &clip,
 					    DRM_PLANE_HELPER_NO_SCALING,
@@ -624,28 +647,52 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	if (format < 0)
 		return format;
 
+	is_yuv = is_yuv_support(fb->pixel_format);
+
 	obj = rockchip_fb_get_gem_obj(fb, 0);
 	if (!obj) {
 		DRM_ERROR("fail to get rockchip gem object from framebuffer\n");
 		return -EINVAL;
 	}
 
+	if (is_yuv) {
+		src.x1 &= (~1) << 16;
+		src.y1 &= (~1) << 16;
+	}
+
 	rk_obj = to_rockchip_obj(obj);
 
 	actual_w = (src.x2 - src.x1) >> 16;
 	actual_h = (src.y2 - src.y1) >> 16;
-	crtc_x = max(0, crtc_x);
-	crtc_y = max(0, crtc_y);
 
-	dsp_stx = crtc_x + crtc->mode.htotal - crtc->mode.hsync_start;
-	dsp_sty = crtc_y + crtc->mode.vtotal - crtc->mode.vsync_start;
+	dsp_stx = dest.x1 + crtc->mode.htotal - crtc->mode.hsync_start;
+	dsp_sty = dest.y1 + crtc->mode.vtotal - crtc->mode.vsync_start;
 
-	offset = (src.x1 >> 16) * (fb->bits_per_pixel >> 3);
+	offset = (src.x1 >> 16) * drm_format_plane_cpp(fb->pixel_format, 0);
 	offset += (src.y1 >> 16) * fb->pitches[0];
-	yrgb_mst = rk_obj->dma_addr + offset;
 
+	yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 	y_vir_stride = fb->pitches[0] >> 2;
 
+	if (is_yuv) {
+		int hsub = drm_format_horz_chroma_subsampling(fb->pixel_format);
+		int vsub = drm_format_vert_chroma_subsampling(fb->pixel_format);
+		int bpp = drm_format_plane_cpp(fb->pixel_format, 1);
+
+		uv_obj = rockchip_fb_get_gem_obj(fb, 1);
+		if (!uv_obj) {
+			DRM_ERROR("fail to get uv object from framebuffer\n");
+			return -EINVAL;
+		}
+		rk_uv_obj = to_rockchip_obj(uv_obj);
+		uv_vir_stride = fb->pitches[1] >> 2;
+
+		offset = (src.x1 >> 16) * bpp / hsub;
+		offset += (src.y1 >> 16) * fb->pitches[1] / vsub;
+
+		uv_mst = rk_uv_obj->dma_addr + offset + fb->offsets[1];
+	}
+
 	/*
 	 * If this plane update changes the plane's framebuffer, (or more
 	 * precisely, if this update has a different framebuffer than the last
@@ -681,6 +728,10 @@ static int vop_update_plane_event(struct drm_plane *plane,
 	VOP_WIN_SET(vop, win, format, format);
 	VOP_WIN_SET(vop, win, yrgb_vir, y_vir_stride);
 	VOP_WIN_SET(vop, win, yrgb_mst, yrgb_mst);
+	if (is_yuv) {
+		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
+		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
+	}
 	val = (actual_h - 1) << 16;
 	val |= (actual_w - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, act_info, val);
-- 
1.7.9.5




From mark.yao at rock-chips.com  Fri Jun 26 03:07:28 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:07:28 +0800
Subject: [PATCH v2 4/5] drm/rockchip: vop: switch cursor plane to window 3
In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1435313249-4549-5-git-send-email-mark.yao@rock-chips.com>

Window 1 support scale and yuv format, it's waste use it for a
cursor, use window 3 is enough.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index f6ef634..40107bb 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -342,13 +342,14 @@ static const struct vop_reg_data vop_init_reg_table[] = {
 /*
  * Note: rk3288 has a dedicated 'cursor' window, however, that window requires
  * special support to get alpha blending working.  For now, just use overlay
- * window 1 for the drm cursor.
+ * window 3 for the drm cursor.
+ *
  */
 static const struct vop_win_data rk3288_vop_win_data[] = {
 	{ .base = 0x00, .phy = &win01_data, .type = DRM_PLANE_TYPE_PRIMARY },
-	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_CURSOR },
+	{ .base = 0x40, .phy = &win01_data, .type = DRM_PLANE_TYPE_OVERLAY },
 	{ .base = 0x00, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
-	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_OVERLAY },
+	{ .base = 0x50, .phy = &win23_data, .type = DRM_PLANE_TYPE_CURSOR },
 	{ .base = 0x00, .phy = &cursor_data, .type = DRM_PLANE_TYPE_OVERLAY },
 };
 
-- 
1.7.9.5




From mark.yao at rock-chips.com  Fri Jun 26 03:07:27 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:07:27 +0800
Subject: [PATCH v2 3/5] drm/rockchip: vop: support plane scale
In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1435313249-4549-4-git-send-email-mark.yao@rock-chips.com>

Win_full support 1/8 to 8 scale down/up engine, support
all format scale.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
Changes in v2:
- Fix scale dest info. 

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  389 ++++++++++++++++++++++++++-
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   96 +++++++
 2 files changed, 483 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 6ca08f8..f6ef634 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -49,6 +49,8 @@
 
 #define VOP_WIN_SET(x, win, name, v) \
 		REG_SET(x, win->base, win->phy->name, v, RELAXED)
+#define VOP_SCL_SET(x, win, name, v) \
+		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
@@ -163,7 +165,37 @@ struct vop_ctrl {
 	struct vop_reg vpost_st_end;
 };
 
+struct vop_scl_regs {
+	struct vop_reg cbr_vsd_mode;
+	struct vop_reg cbr_vsu_mode;
+	struct vop_reg cbr_hsd_mode;
+	struct vop_reg cbr_ver_scl_mode;
+	struct vop_reg cbr_hor_scl_mode;
+	struct vop_reg yrgb_vsd_mode;
+	struct vop_reg yrgb_vsu_mode;
+	struct vop_reg yrgb_hsd_mode;
+	struct vop_reg yrgb_ver_scl_mode;
+	struct vop_reg yrgb_hor_scl_mode;
+	struct vop_reg line_load_mode;
+	struct vop_reg cbr_axi_gather_num;
+	struct vop_reg yrgb_axi_gather_num;
+	struct vop_reg vsd_cbr_gt2;
+	struct vop_reg vsd_cbr_gt4;
+	struct vop_reg vsd_yrgb_gt2;
+	struct vop_reg vsd_yrgb_gt4;
+	struct vop_reg bic_coe_sel;
+	struct vop_reg cbr_axi_gather_en;
+	struct vop_reg yrgb_axi_gather_en;
+
+	struct vop_reg lb_mode;
+	struct vop_reg scale_yrgb_x;
+	struct vop_reg scale_yrgb_y;
+	struct vop_reg scale_cbcr_x;
+	struct vop_reg scale_cbcr_y;
+};
+
 struct vop_win_phy {
+	const struct vop_scl_regs *scl;
 	const uint32_t *data_formats;
 	uint32_t nformats;
 
@@ -212,7 +244,36 @@ static const uint32_t formats_234[] = {
 	DRM_FORMAT_RGB565,
 };
 
+static const struct vop_scl_regs win_full_scl = {
+	.cbr_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 31),
+	.cbr_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 30),
+	.cbr_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 28),
+	.cbr_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 26),
+	.cbr_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 24),
+	.yrgb_vsd_mode = VOP_REG(WIN0_CTRL1, 0x1, 23),
+	.yrgb_vsu_mode = VOP_REG(WIN0_CTRL1, 0x1, 22),
+	.yrgb_hsd_mode = VOP_REG(WIN0_CTRL1, 0x3, 20),
+	.yrgb_ver_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 18),
+	.yrgb_hor_scl_mode = VOP_REG(WIN0_CTRL1, 0x3, 16),
+	.line_load_mode = VOP_REG(WIN0_CTRL1, 0x1, 15),
+	.cbr_axi_gather_num = VOP_REG(WIN0_CTRL1, 0x7, 12),
+	.yrgb_axi_gather_num = VOP_REG(WIN0_CTRL1, 0xf, 8),
+	.vsd_cbr_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 7),
+	.vsd_cbr_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 6),
+	.vsd_yrgb_gt2 = VOP_REG(WIN0_CTRL1, 0x1, 5),
+	.vsd_yrgb_gt4 = VOP_REG(WIN0_CTRL1, 0x1, 4),
+	.bic_coe_sel = VOP_REG(WIN0_CTRL1, 0x3, 2),
+	.cbr_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 1),
+	.yrgb_axi_gather_en = VOP_REG(WIN0_CTRL1, 0x1, 0),
+	.lb_mode = VOP_REG(WIN0_CTRL0, 0x7, 5),
+	.scale_yrgb_x = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 0x0),
+	.scale_yrgb_y = VOP_REG(WIN0_SCL_FACTOR_YRGB, 0xffff, 16),
+	.scale_cbcr_x = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 0x0),
+	.scale_cbcr_y = VOP_REG(WIN0_SCL_FACTOR_CBR, 0xffff, 16),
+};
+
 static const struct vop_win_phy win01_data = {
+	.scl = &win_full_scl,
 	.data_formats = formats_01,
 	.nformats = ARRAY_SIZE(formats_01),
 	.enable = VOP_REG(WIN0_CTRL0, 0x1, 0),
@@ -351,6 +412,15 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
 	}
 }
 
+static inline int _get_vskiplines(uint32_t srch, uint32_t dsth)
+{
+	if (srch >= (uint32_t)(4 * dsth * MIN_SCL_FT_AFTER_VSKIP))
+		return 4;
+	else if (srch >= (uint32_t)(2 * dsth * MIN_SCL_FT_AFTER_VSKIP))
+		return 2;
+	return 1;
+}
+
 static enum vop_data_format vop_convert_format(uint32_t format)
 {
 	switch (format) {
@@ -538,6 +608,310 @@ static void vop_disable(struct drm_crtc *crtc)
 	pm_runtime_put(vop->dev);
 }
 
+static int _vop_cal_yrgb_lb_mode(int width)
+{
+	int lb_mode = LB_RGB_1920X5;
+
+	if (width > 2560)
+		lb_mode = LB_RGB_3840X2;
+	else if (width > 1920)
+		lb_mode = LB_RGB_2560X4;
+
+	return lb_mode;
+}
+
+static int _vop_cal_cbcr_lb_mode(int width)
+{
+	int lb_mode = LB_YUV_2560X8;
+
+	if (width > 2560)
+		lb_mode = LB_RGB_3840X2;
+	else if (width > 1920)
+		lb_mode = LB_RGB_2560X4;
+	else if (width > 1280)
+		lb_mode = LB_YUV_3840X5;
+
+	return lb_mode;
+}
+
+static void _vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
+			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+			     uint32_t dst_h, uint32_t pixel_format)
+{
+	uint16_t yrgb_hor_scl_mode = SCALE_NONE;
+	uint16_t yrgb_ver_scl_mode = SCALE_NONE;
+	uint16_t cbr_hor_scl_mode = SCALE_NONE;
+	uint16_t cbr_ver_scl_mode = SCALE_NONE;
+	uint16_t yrgb_hsd_mode = SCALE_DOWN_BIL;
+	uint16_t cbr_hsd_mode = SCALE_DOWN_BIL;
+	uint16_t yrgb_vsd_mode = SCALE_DOWN_BIL;
+	uint16_t cbr_vsd_mode = SCALE_DOWN_BIL;
+	uint16_t yrgb_vsu_mode = SCALE_UP_BIL;
+	uint16_t cbr_vsu_mode = SCALE_UP_BIL;
+	uint16_t scale_yrgb_x = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_yrgb_y = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_cbcr_x = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	uint16_t scale_cbcr_y = 1 << SCL_FT_DEFAULT_FIXPOINT_SHIFT;
+	int hsub = drm_format_horz_chroma_subsampling(pixel_format);
+	int vsub = drm_format_vert_chroma_subsampling(pixel_format);
+	bool is_yuv = is_yuv_support(pixel_format);
+	uint16_t vsd_yrgb_gt4 = 0;
+	uint16_t vsd_yrgb_gt2 = 0;
+	uint16_t vsd_cbr_gt4 = 0;
+	uint16_t vsd_cbr_gt2 = 0;
+	uint16_t yrgb_src_w = src_w;
+	uint16_t yrgb_src_h = src_h;
+	uint16_t yrgb_dst_w = dst_w;
+	uint16_t yrgb_dst_h = dst_h;
+	uint16_t cbcr_src_w;
+	uint16_t cbcr_src_h;
+	uint16_t cbcr_dst_w;
+	uint16_t cbcr_dst_h;
+	uint32_t vdmult;
+	uint16_t lb_mode;
+
+	if (((yrgb_dst_w << 3) <= yrgb_src_w) ||
+	    ((yrgb_dst_h << 3) <= yrgb_src_h) ||
+	    yrgb_dst_w > 3840) {
+		DRM_ERROR("yrgb scale exceed 8,src[%dx%d] dst[%dx%d]\n",
+			  yrgb_src_w, yrgb_src_h, yrgb_dst_w, yrgb_dst_h);
+		return;
+	}
+
+	if (yrgb_src_w < yrgb_dst_w)
+		yrgb_hor_scl_mode = SCALE_UP;
+	else if (yrgb_src_w > yrgb_dst_w)
+		yrgb_hor_scl_mode = SCALE_DOWN;
+	else
+		yrgb_hor_scl_mode = SCALE_NONE;
+
+	if (yrgb_src_h < yrgb_dst_h)
+		yrgb_ver_scl_mode = SCALE_UP;
+	else if (yrgb_src_h  > yrgb_dst_h)
+		yrgb_ver_scl_mode = SCALE_DOWN;
+	else
+		yrgb_ver_scl_mode = SCALE_NONE;
+
+	if (is_yuv) {
+		cbcr_src_w = src_w / hsub;
+		cbcr_src_h = src_h / vsub;
+		cbcr_dst_w = dst_w;
+		cbcr_dst_h = dst_h;
+		if ((cbcr_dst_w << 3) <= cbcr_src_w ||
+		    (cbcr_dst_h << 3) <= cbcr_src_h ||
+		    cbcr_src_w > 3840 ||
+		    cbcr_src_w == 0)
+			DRM_ERROR("cbcr scale failed,src[%dx%d] dst[%dx%d]\n",
+				  cbcr_src_w, cbcr_src_h,
+				  cbcr_dst_w, cbcr_dst_h);
+		if (cbcr_src_w < cbcr_dst_w)
+			cbr_hor_scl_mode = SCALE_UP;
+		else if (cbcr_src_w > cbcr_dst_w)
+			cbr_hor_scl_mode = SCALE_DOWN;
+
+		if (cbcr_src_h < cbcr_dst_h)
+			cbr_ver_scl_mode = SCALE_UP;
+		else if (cbcr_src_h > cbcr_dst_h)
+			cbr_ver_scl_mode = SCALE_DOWN;
+	}
+	/*
+	 * line buffer mode
+	 */
+	if (is_yuv) {
+		if (yrgb_hor_scl_mode == SCALE_DOWN && yrgb_dst_w > 2560)
+			lb_mode = LB_RGB_3840X2;
+		else if (cbr_hor_scl_mode == SCALE_DOWN)
+			lb_mode = _vop_cal_cbcr_lb_mode(cbcr_dst_w);
+		else
+			lb_mode = _vop_cal_cbcr_lb_mode(cbcr_src_w);
+	} else {
+		if (yrgb_hor_scl_mode == SCALE_DOWN)
+			lb_mode = _vop_cal_yrgb_lb_mode(yrgb_dst_w);
+		else
+			lb_mode = _vop_cal_yrgb_lb_mode(yrgb_src_w);
+	}
+
+	switch (lb_mode) {
+	case LB_YUV_3840X5:
+	case LB_YUV_2560X8:
+	case LB_RGB_1920X5:
+	case LB_RGB_1280X8:
+		yrgb_vsu_mode = SCALE_UP_BIC;
+		cbr_vsu_mode  = SCALE_UP_BIC;
+		break;
+	case LB_RGB_3840X2:
+		if (yrgb_ver_scl_mode != SCALE_NONE)
+			DRM_ERROR("ERROR : not allow yrgb ver scale\n");
+		if (cbr_ver_scl_mode != SCALE_NONE)
+			DRM_ERROR("ERROR : not allow cbcr ver scale\n");
+		break;
+	case LB_RGB_2560X4:
+		yrgb_vsu_mode = SCALE_UP_BIL;
+		cbr_vsu_mode  = SCALE_UP_BIL;
+		break;
+	default:
+		DRM_ERROR("unsupport lb_mode:%d\n", lb_mode);
+		break;
+	}
+	/*
+	 * (1.1)YRGB HOR SCALE FACTOR
+	 */
+	switch (yrgb_hor_scl_mode) {
+	case SCALE_UP:
+		scale_yrgb_x = GET_SCL_FT_BIC(yrgb_src_w, yrgb_dst_w);
+		break;
+	case SCALE_DOWN:
+		switch (yrgb_hsd_mode) {
+		case SCALE_DOWN_BIL:
+			scale_yrgb_x = GET_SCL_FT_BILI_DN(yrgb_src_w,
+							  yrgb_dst_w);
+			break;
+		case SCALE_DOWN_AVG:
+			scale_yrgb_x = GET_SCL_FT_AVRG(yrgb_src_w, yrgb_dst_w);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_hsd_mode:%d\n",
+				  yrgb_hsd_mode);
+			break;
+		}
+		break;
+	}
+
+	/*
+	 * (1.2)YRGB VER SCALE FACTOR
+	 */
+	switch (yrgb_ver_scl_mode) {
+	case SCALE_UP:
+		switch (yrgb_vsu_mode) {
+		case SCALE_UP_BIL:
+			scale_yrgb_y = GET_SCL_FT_BILI_UP(yrgb_src_h,
+							  yrgb_dst_h);
+			break;
+		case SCALE_UP_BIC:
+			if (yrgb_src_h < 3)
+				DRM_ERROR("yrgb_src_h should greater than 3\n");
+			scale_yrgb_y = GET_SCL_FT_BIC(yrgb_src_h, yrgb_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_vsu_mode:%d\n",
+				  yrgb_vsu_mode);
+			break;
+		}
+		break;
+	case SCALE_DOWN:
+		switch (yrgb_vsd_mode) {
+		case SCALE_DOWN_BIL:
+			vdmult = _get_vskiplines(yrgb_src_h, yrgb_dst_h);
+			scale_yrgb_y = GET_SCL_FT_BILI_DN_VSKIP(yrgb_src_h,
+								yrgb_dst_h,
+								vdmult);
+			if (vdmult == 4) {
+				vsd_yrgb_gt4 = 1;
+				vsd_yrgb_gt2 = 0;
+			} else if (vdmult == 2) {
+				vsd_yrgb_gt4 = 0;
+				vsd_yrgb_gt2 = 1;
+			}
+			break;
+		case SCALE_DOWN_AVG:
+			scale_yrgb_y = GET_SCL_FT_AVRG(yrgb_src_h, yrgb_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport yrgb_vsd_mode:%d\n",
+				  yrgb_vsd_mode);
+			break;
+		}
+		break;
+	}
+	/*
+	 * (2.1)CBCR HOR SCALE FACTOR
+	 */
+	switch (cbr_hor_scl_mode) {
+	case SCALE_UP:
+		scale_cbcr_x = GET_SCL_FT_BIC(cbcr_src_w, cbcr_dst_w);
+		break;
+	case SCALE_DOWN:
+		switch (cbr_hsd_mode) {
+		case SCALE_DOWN_BIL:
+			scale_cbcr_x = GET_SCL_FT_BILI_DN(cbcr_src_w,
+							  cbcr_dst_w);
+			break;
+		case SCALE_DOWN_AVG:
+			scale_cbcr_x = GET_SCL_FT_AVRG(cbcr_src_w, cbcr_dst_w);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_hsd_mode:%d\n", cbr_hsd_mode);
+			break;
+		}
+		break;
+	}
+
+	/*
+	 * (2.2)CBCR VER SCALE FACTOR
+	 */
+	switch (cbr_ver_scl_mode) {
+	case SCALE_UP:
+		switch (cbr_vsu_mode) {
+		case SCALE_UP_BIL:
+			scale_cbcr_y = GET_SCL_FT_BILI_UP(cbcr_src_h,
+							  cbcr_dst_h);
+			break;
+		case SCALE_UP_BIC:
+			if (cbcr_src_h < 3)
+				DRM_ERROR("cbcr_src_h need greater than 3 !\n");
+			scale_cbcr_y = GET_SCL_FT_BIC(cbcr_src_h, cbcr_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_vsu_mode:%d\n", cbr_vsu_mode);
+			break;
+		}
+		break;
+	case SCALE_DOWN:
+		switch (cbr_vsd_mode) {
+		case SCALE_DOWN_BIL:
+			vdmult = _get_vskiplines(cbcr_src_h, cbcr_dst_h);
+			scale_cbcr_y = GET_SCL_FT_BILI_DN_VSKIP(cbcr_src_h,
+								cbcr_dst_h,
+								vdmult);
+			if (vdmult == 4) {
+				vsd_cbr_gt4 = 1;
+				vsd_cbr_gt2 = 0;
+			} else if (vdmult == 2) {
+				vsd_cbr_gt4 = 0;
+				vsd_cbr_gt2 = 1;
+			}
+			break;
+		case SCALE_DOWN_AVG:
+			scale_cbcr_y = GET_SCL_FT_AVRG(cbcr_src_h, cbcr_dst_h);
+			break;
+		default:
+			DRM_ERROR("unsupport cbr_vsd_mode:%d\n", cbr_vsd_mode);
+			break;
+		}
+		break;
+	}
+
+	VOP_SCL_SET(vop, win, yrgb_hor_scl_mode, yrgb_hor_scl_mode);
+	VOP_SCL_SET(vop, win, yrgb_ver_scl_mode, yrgb_ver_scl_mode);
+	VOP_SCL_SET(vop, win, cbr_hor_scl_mode, cbr_hor_scl_mode);
+	VOP_SCL_SET(vop, win, cbr_ver_scl_mode, cbr_ver_scl_mode);
+	VOP_SCL_SET(vop, win, lb_mode, lb_mode);
+	VOP_SCL_SET(vop, win, yrgb_hsd_mode, yrgb_hsd_mode);
+	VOP_SCL_SET(vop, win, cbr_hsd_mode, cbr_hsd_mode);
+	VOP_SCL_SET(vop, win, yrgb_vsd_mode, yrgb_vsd_mode);
+	VOP_SCL_SET(vop, win, cbr_vsd_mode, cbr_vsd_mode);
+	VOP_SCL_SET(vop, win, yrgb_vsu_mode, yrgb_vsu_mode);
+	VOP_SCL_SET(vop, win, cbr_vsu_mode, cbr_vsu_mode);
+	VOP_SCL_SET(vop, win, scale_yrgb_x, scale_yrgb_x);
+	VOP_SCL_SET(vop, win, scale_yrgb_y, scale_yrgb_y);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt4, vsd_yrgb_gt4);
+	VOP_SCL_SET(vop, win, vsd_yrgb_gt2, vsd_yrgb_gt2);
+	VOP_SCL_SET(vop, win, scale_cbcr_x, scale_cbcr_x);
+	VOP_SCL_SET(vop, win, scale_cbcr_y, scale_cbcr_y);
+	VOP_SCL_SET(vop, win, vsd_cbr_gt4, vsd_cbr_gt4);
+	VOP_SCL_SET(vop, win, vsd_cbr_gt2, vsd_cbr_gt2);
+}
+
 /*
  * Caller must hold vsync_mutex.
  */
@@ -624,6 +998,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 		.y2 = crtc->mode.vdisplay,
 	};
 	bool can_position = plane->type != DRM_PLANE_TYPE_PRIMARY;
+	int min_scale = win->phy->scl ? 0x02000 : DRM_PLANE_HELPER_NO_SCALING;
+	int max_scale = win->phy->scl ? 0x80000 : DRM_PLANE_HELPER_NO_SCALING;
 
 	if (drm_format_num_planes(fb->pixel_format) > 2) {
 		DRM_ERROR("unsupport more than 2 plane format[%08x]\n",
@@ -633,8 +1009,8 @@ static int vop_update_plane_event(struct drm_plane *plane,
 
 	ret = drm_plane_helper_check_update(plane, crtc, fb,
 					    &src, &dest, &clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
+					    min_scale,
+					    max_scale,
 					    can_position, false, &visible);
 	if (ret)
 		return ret;
@@ -732,9 +1108,18 @@ static int vop_update_plane_event(struct drm_plane *plane,
 		VOP_WIN_SET(vop, win, uv_vir, uv_vir_stride);
 		VOP_WIN_SET(vop, win, uv_mst, uv_mst);
 	}
+
+	if (win->phy->scl)
+		_vop_cal_scl_fac(vop, win, actual_w, actual_h,
+				 dest.x2 - dest.x1, dest.y2 - dest.y1,
+				 fb->pixel_format);
+
 	val = (actual_h - 1) << 16;
 	val |= (actual_w - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, act_info, val);
+
+	val = (dest.y2 - dest.y1 - 1) << 16;
+	val |= (dest.x2 - dest.x1 - 1) & 0xffff;
 	VOP_WIN_SET(vop, win, dsp_info, val);
 	val = (dsp_sty - 1) << 16;
 	val |= (dsp_stx - 1) & 0xffff;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 63e9b3a..edacdee 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -198,4 +198,100 @@ enum factor_mode {
 	ALPHA_SRC_GLOBAL,
 };
 
+enum scale_mode {
+	SCALE_NONE = 0x0,
+	SCALE_UP   = 0x1,
+	SCALE_DOWN = 0x2
+};
+
+enum lb_mode {
+	LB_YUV_3840X5 = 0x0,
+	LB_YUV_2560X8 = 0x1,
+	LB_RGB_3840X2 = 0x2,
+	LB_RGB_2560X4 = 0x3,
+	LB_RGB_1920X5 = 0x4,
+	LB_RGB_1280X8 = 0x5
+};
+
+enum sacle_up_mode {
+	SCALE_UP_BIL = 0x0,
+	SCALE_UP_BIC = 0x1
+};
+
+enum scale_down_mode {
+	SCALE_DOWN_BIL = 0x0,
+	SCALE_DOWN_AVG = 0x1
+};
+
+#define CUBIC_PRECISE  0
+#define CUBIC_SPLINE   1
+#define CUBIC_CATROM   2
+#define CUBIC_MITCHELL 3
+
+#define CUBIC_MODE_SELETION      CUBIC_PRECISE
+
+#define SCL_FT_BILI_DN_FIXPOINT_SHIFT	12
+#define SCL_FT_BILI_DN_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_FT_BILI_DN_FIXPOINT_SHIFT)))
+
+#define SCL_FT_BILI_UP_FIXPOINT_SHIFT	16
+
+#define SCL_FT_AVRG_FIXPOINT_SHIFT	16
+#define SCL_FT_AVRG_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_FT_AVRG_FIXPOINT_SHIFT)))
+
+#define SCL_FT_BIC_FIXPOINT_SHIFT	16
+#define SCL_FT_BIC_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_FT_BIC_FIXPOINT_SHIFT)))
+
+#define SCL_FT_DEFAULT_FIXPOINT_SHIFT    12
+#define SCL_FT_VSDBIL_FIXPOINT_SHIFT     12
+
+#define SCL_CAL(src, dst, shift) \
+		((((src) * 2 - 3) << ((shift) - 1)) / ((dst) - 1))
+#define GET_SCL_FT_BILI_DN(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BILI_DN_FIXPOINT_SHIFT)
+#define GET_SCL_FT_BILI_UP(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BILI_UP_FIXPOINT_SHIFT)
+#define GET_SCL_FT_BIC(src, dst) \
+		SCL_CAL(src, dst, SCL_FT_BIC_FIXPOINT_SHIFT)
+
+#define GET_SCL_DN_ACT_HEIGHT(src_h, vdmult) \
+		(((src_h) + (vdmult) - 1) / (vdmult))
+
+#define MIN_SCL_FT_AFTER_VSKIP	1
+#define GET_SCL_FT_BILI_DN_VSKIP(src_h, dst_h, vdmult) \
+		((GET_SCL_DN_ACT_HEIGHT((src_h), (vdmult)) == (dst_h)) \
+			? (GET_SCL_FT_BILI_DN((src_h), (dst_h))/(vdmult)) \
+			: GET_SCL_FT_BILI_DN(GET_SCL_DN_ACT_HEIGHT((src_h), \
+					     (vdmult)), (dst_h)))
+
+#define GET_SCL_FT_AVRG(src, dst) \
+		(((dst) << ((SCL_FT_AVRG_FIXPOINT_SHIFT) + 1)) \
+		 / (2 * (src) - 1))
+
+#define SCL_COOR_ACC_FIXPOINT_SHIFT	16
+#define SCL_COOR_ACC_FIXPOINT_ONE	(1 << SCL_COOR_ACC_FIXPOINT_SHIFT)
+#define SCL_COOR_ACC_FIXPOINT(x) \
+		((INT32)((x)*(1 << SCL_COOR_ACC_FIXPOINT_SHIFT)))
+#define SCL_COOR_ACC_FIXPOINT_REVERT(x)	\
+		((((x) >> (SCL_COOR_ACC_FIXPOINT_SHIFT-1)) + 1) >> 1)
+
+#define SCL_GET_COOR_ACC_FIXPOINT(scale, shift)  \
+		((scale) << (SCL_COOR_ACC_FIXPOINT_SHIFT - (shift)))
+#define SCL_FILTER_FT_FIXPOINT_SHIFT	8
+#define SCL_FILTER_FT_FIXPOINT_ONE	(1 << SCL_FILTER_FT_FIXPOINT_SHIFT)
+#define SCL_FILTER_FT_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_FILTER_FT_FIXPOINT_SHIFT)))
+#define SCL_FILTER_FT_FIXPOINT_REVERT(x) \
+		((((x) >> (SCL_FILTER_FT_FIXPOINT_SHIFT - 1)) + 1) >> 1)
+
+#define SCL_GET_FILTER_FT_FIXPOINT(ca, shift) \
+		(((ca) >> ((shift)-SCL_FILTER_FT_FIXPOINT_SHIFT)) & \
+		 (SCL_FILTER_FT_FIXPOINT_ONE - 1))
+
+#define SCL_OFFSET_FIXPOINT_SHIFT	8
+#define SCL_OFFSET_FIXPOINT(x) \
+		((INT32)((x) * (1 << SCL_OFFSET_FIXPOINT_SHIFT)))
+
 #endif /* _ROCKCHIP_DRM_VOP_H */
-- 
1.7.9.5




From mark.yao at rock-chips.com  Fri Jun 26 03:10:32 2015
From: mark.yao at rock-chips.com (Mark Yao)
Date: Fri, 26 Jun 2015 18:10:32 +0800
Subject: [PATCH v2 5/5] drm/rockchip: default enable win2/3 area0 bit
In-Reply-To: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
References: <1435313249-4549-1-git-send-email-mark.yao@rock-chips.com>
Message-ID: <1435313432-4923-1-git-send-email-mark.yao@rock-chips.com>

Win2/3 support 4 area display, but now havn't found a suitable
way to use it, and it enable by win gate and area gate,
so default enable area0 gate, so that its behaviour just like a
win.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
Changes in v2: None

 drivers/gpu/drm/rockchip/rockchip_drm_vop.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 40107bb..e001d26 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -337,6 +337,12 @@ static const struct vop_reg_data vop_init_reg_table[] = {
 	{DSP_CTRL0, 0x00000000},
 	{WIN0_CTRL0, 0x00000080},
 	{WIN1_CTRL0, 0x00000080},
+	/*
+	 * Todo: win2/3 support area func, but now havn't found a suitable
+	 * way to use it, so default enable area0 as a win display.
+	 */
+	{WIN2_CTRL0, 0x00000010},
+	{WIN3_CTRL0, 0x00000010},
 };
 
 /*
-- 
1.7.9.5




From bamv2005 at gmail.com  Fri Jun 26 06:30:48 2015
From: bamv2005 at gmail.com (Bamvor Zhang)
Date: Fri, 26 Jun 2015 21:30:48 +0800
Subject: [PATCH 0/4] arm64: add initial support for the Rockchip rk3368
In-Reply-To: <2154359.YLevLOlh2Y@diego>
References: <1650408.ovnAjReNFJ@diego> <558CD6AE.7030505@gmail.com>
 <2154359.YLevLOlh2Y@diego>
Message-ID: <CAOijeYKpAuBqw0t2RtbWOweGigqxTXO0dNxDGj66SWjFggOYpg@mail.gmail.com>

Hi, Heiko

2015-06-26 15:17 GMT+08:00 Heiko St?bner <heiko at sntech.de>:
> Hi Bamvor,
>
> Am Freitag, 26. Juni 2015, 12:35:58 schrieb Bamvor Jian Zhang:
>> Could I test the code on rk3368 STB such as EKB368, CSA90?
>> Is there some documents about it?
>
> General information on flashing generic Rockchip devices can be found on [0].
> That didn't change for the rk3368 it seems - although a device _might_ be
> locked down to prevent reflashing it seems.
>
> You will of course also need a serial console on the device for the time
> being, so finding the test-points and soldering is probably required.
Thanks, I will try it.

bamvor
>
>
> Heiko
>
>
> [0] http://linux-rockchip.info
>
>
>> On 06/26/2015 02:12 AM, Heiko St?bner wrote:
>> > This adds initial support for the new rk3368 ARM64 soc from Rockchip.
>> >
>> > Overall it looks like someone dropped some A53 cores into a rk3288, so
>> > it shares a lot of peripherals that only differ in details. Therefore
>> > stuff like the mmc, usb, spi, i2c controllers work out of the box.
>> > The support for the gmac already made it into the merge window as well
>> > as the pinctrl support.
>> >
>> > Interestingly, in its core the rk3368 seems trying to be a model student
>> > with psci for smp and using scpi for ddr frequency scaling, although I
>> > currently do not understand how the mailbox works yet. The display
>> > controllers also are only minimally different so I'm hopefully to have
>> > working graphics in the near-ish future :-)
>> >
>> >
>> > As mentioned in the dts patch, this series depends on the dt-binding
>> > header for the clock ids, so will need a shared branch once this is ready.
>> >
>> > Heiko Stuebner (4):
>> >    arm64: add Rockchip architecture entry
>> >    arm64: defconfig: enable ARCH_ROCKCHIP
>> >    arm64: dts: add Rockchip rk3368 core dtsi and board dts for the r88
>> >
>> >      board
>> >
>> >    dt-bindings: document rk3368 R89 board from Rockchip
>> >
>> >   Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
>> >   arch/arm64/Kconfig                                 |  10 +
>> >   arch/arm64/boot/dts/Makefile                       |   1 +
>> >   arch/arm64/boot/dts/rockchip/Makefile              |   5 +
>> >   arch/arm64/boot/dts/rockchip/rk3368-r88.dts        | 353 ++++++++
>> >   arch/arm64/boot/dts/rockchip/rk3368.dtsi           | 900
>> >   +++++++++++++++++++++ arch/arm64/configs/defconfig
>> >    |   2 +
>> >   7 files changed, 1275 insertions(+)
>> >   create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
>> >   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
>> >   create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi
>


From wxt at rock-chips.com  Mon Jun 29 01:16:36 2015
From: wxt at rock-chips.com (Caesar Wang)
Date: Mon, 29 Jun 2015 16:16:36 +0800
Subject: [PATCH v14 2/3] power-domain: rockchip: add power domain driver
In-Reply-To: <CAPDyKFqa9cQin2HUFuLO_-sSkeASSr08b-3DZ5xGbYHQBPxKag@mail.gmail.com>
References: <1429862868-14218-1-git-send-email-wxt@rock-chips.com>
 <1429862868-14218-3-git-send-email-wxt@rock-chips.com>
 <CAPDyKFrBzZjOVZzq9unQQwm2BSA0kzeT7EE8_kSpH_udMKjo6A@mail.gmail.com>
 <557CF1D6.4090506@163.com>
 <CAPDyKFqa9cQin2HUFuLO_-sSkeASSr08b-3DZ5xGbYHQBPxKag@mail.gmail.com>
Message-ID: <5590FEE4.3030709@rock-chips.com>

Hi Uffe,

? 2015?06?25? 23:33, Ulf Hansson ??:
> [...]
>
>>>> +#include <linux/clk-provider.h>
>>> clk-provider.h, why?
>>
>> The following is needed.
>>
>> _clk_get_name(clk)
> I see, you need it for for the dev_dbg().
>
> I think you shall use "%pC" as the formatting string for the dev_dbg()
> message, since that will take care of printing the clock name for you.

Yes, the "%pC" can do the similar thing.
Done, fixed in next patch.

> [...]
>
>>>> +static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool
>>>> power_on)
>>>> +{
>>>> +       int i;
>>>> +
>>>> +       mutex_lock(&pd->pmu->mutex);
>>> I don't quite understand why you need a lock, what are you protecting and
>>> why?
>>
>> Says:
>> [ 3551.678762] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3551.899180] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3551.905958] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3551.912832] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3551.919730] rockchip_pd_power:139: mutex_lock
>> [ 3551.924130] rockchip_pd_power:167,mutex_unlock
>> [ 3563.827295] rockchip_pd_power:139: mutex_lock
>> [ 3563.831753] rockchip_pd_power:167,mutex_unlock
>> [ 3563.836216] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3564.058989] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3564.065659] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3564.072354] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3564.079047] rockchip_pd_power:139: mutex_lock
>> [ 3564.083426] rockchip_pd_power:167,mutex_unlock
>> [ 3611.665726] rockchip_pd_power:139: mutex_lock
>> [ 3611.670206] rockchip_pd_power:167,mutex_unlock
>> [ 3611.674692] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3611.899160] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3611.905938] mali ffa30000.gpu: starting device in power domain 'pd_gpu'
>> [ 3611.912818] mali ffa30000.gpu: stopping device in power domain 'pd_gpu'
>> [ 3611.919689] rockchip_pd_power:139: mutex_lock
>> [ 3611.924090] rockchip_pd_power:167,mutex_unlock
>> [ 3623.848296] rockchip_pd_power:139: mutex_lock
>> [ 3623.852752] rockchip_pd_power:167,mutex_unlock
>>
>>
>>
>>
>>>> +
>>>> +       if (rockchip_pmu_domain_is_on(pd) != power_on) {
>>>> +               for (i = 0; i < pd->num_clks; i++)
>>>> +                       clk_enable(pd->clks[i]);
>>>> +
>>>> +               if (!power_on) {
>>>> +                       /* FIXME: add code to save AXI_QOS */
>>>> +
>>>> +                       /* if powering down, idle request to NIU first */
>>>> +                       rockchip_pmu_set_idle_request(pd, true);
>>>> +               }
>>>> +
>>>> +               rockchip_do_pmu_set_power_domain(pd, power_on);
>>>> +
>>>> +               if (power_on) {
>>>> +                       /* if powering up, leave idle mode */
>>>> +                       rockchip_pmu_set_idle_request(pd, false);
>>>> +
>>>> +                       /* FIXME: add code to restore AXI_QOS */
>>>> +               }
>>>> +
>>>> +               for (i = pd->num_clks - 1; i >= 0; i--)
>>>> +                       clk_disable(pd->clks[i]);
>>>> +       }
>>>> +
>>>> +       mutex_unlock(&pd->pmu->mutex);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int rockchip_pd_power_on(struct generic_pm_domain *domain)
>>>> +{
>>>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>>>> +
>>>> +       return rockchip_pd_power(pd, true);
>>>> +}
>>>> +
>>>> +static int rockchip_pd_power_off(struct generic_pm_domain *domain)
>>>> +{
>>>> +       struct rockchip_pm_domain *pd = to_rockchip_pd(domain);
>>>> +
>>>> +       return rockchip_pd_power(pd, false);
>>>> +}
>>>> +
>>>> +static int rockchip_pd_attach_dev(struct generic_pm_domain *genpd,
>>>> +                                 struct device *dev)
>>>> +{
>>>> +       struct clk *clk;
>>>> +       int i;
>>>> +       int error;
>>>> +
>>>> +       dev_dbg(dev, "attaching to power domain '%s'\n", genpd->name);
>>>> +
>>>> +       error = pm_clk_create(dev);
>>>> +       if (error) {
>>>> +               dev_err(dev, "pm_clk_create failed %d\n", error);
>>>> +               return error;
>>>> +       }
>>>> +
>>>> +       i = 0;
>>>> +       while ((clk = of_clk_get(dev->of_node, i++)) && !IS_ERR(clk)) {
>>> This loop adds all available device clocks to the PM clock list. I
>>> wonder if this could be considered as a common thing and if so, we
>>> might want to extend the pm_clk API with this.
>>
>> There are several reasons as follows:
>>
>>      Firstly, the clocks need be turned off to save power when
>>      the system enter the suspend state. So we need to enumerate the clocks
>>      in the dts. In order to power domain can turn on and off.
>>
>>      Secondly, the reset-circuit should reset be synchronous on rk3288, then
>> sync revoked.
>>      So we need to enable clocks of all devices.
> I think you misinterpreted my previous answer. Instead of fetching all
> clocks for a device and manually create the pm_clk list as you do
> here, I was suggesting to make this a part of the pm clk API.
>
> I would happily support such an API, but I can't tell what the other
> maintainers think.

Sorry, this is my misunderstanding.

Here, I agree your point. I will glad to use it if you support such an API.
I will send patch v16 with it if you have the implementation code.

>>>> +               dev_dbg(dev, "adding clock '%s' to list of PM clocks\n",
>>>> +                       __clk_get_name(clk));
>>>> +               error = pm_clk_add_clk(dev, clk);
>>>> +               clk_put(clk);
>>>> +               if (error) {
>>>> +                       dev_err(dev, "pm_clk_add_clk failed %d\n",
>>>> error);
>>>> +                       pm_clk_destroy(dev);
>>>> +                       return error;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
> [...]
>
>>>> +
>>>> +static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
>>>> +                                     struct device_node *node)
>>>> +{
>>>> +       const struct rockchip_domain_info *pd_info;
>>>> +       struct rockchip_pm_domain *pd;
>>>> +       struct clk *clk;
>>>> +       int clk_cnt;
>>>> +       int i;
>>>> +       u32 id;
>>>> +       int error;
>>>> +
>>>> +       error = of_property_read_u32(node, "reg", &id);
>>>> +       if (error) {
>>>> +               dev_err(pmu->dev,
>>>> +                       "%s: failed to retrieve domain id (reg): %d\n",
>>>> +                       node->name, error);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       if (id >= pmu->info->num_domains) {
>>>> +               dev_err(pmu->dev, "%s: invalid domain id %d\n",
>>>> +                       node->name, id);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       pd_info = &pmu->info->domain_info[id];
>>>> +       if (!pd_info) {
>>>> +               dev_err(pmu->dev, "%s: undefined domain id %d\n",
>>>> +                       node->name, id);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       clk_cnt = of_count_phandle_with_args(node, "clocks",
>>>> "#clock-cells");
>>>> +       pd = devm_kzalloc(pmu->dev,
>>>> +                         sizeof(*pd) + clk_cnt * sizeof(pd->clks[0]),
>>>> +                         GFP_KERNEL);
>>>> +       if (!pd)
>>>> +               return -ENOMEM;
>>>> +
>>>> +       pd->info = pd_info;
>>>> +       pd->pmu = pmu;
>>>> +
>>>> +       for (i = 0; i < clk_cnt; i++) {
>>> This loop is similar to the one when creates the PM clock list in the
>>> rockchip_pd_attach_dev().
>>>
>>> What's the reason you don't want to use pm clk for these clocks?
>>>
>> Ditto.
> I don't follow. Can't you do the exact same thing via the pm clk API,
> can you please elaborate!?
>

Although I'm glad to use the pm clk API, something to prevent that.

As perivous versions told about:

At the moment, all the device clocks being listed in the power-domains 
itself,
I know someone wish was to get the clocks by reading the clocks from the 
device nodes,

I think reading the clocks from the devices if we via the pm clk API.
I concerned that we can't ensure the consumption enough good during the 
suspend state.

Meanwhile, as the pervious patch v7 said:

     the clocks need be turned off to save power when the system enter 
the suspend state.
So we need to enumerate the clocks in the dts. In order to power domain 
can turn on and off.

     the reset-circuit should reset be synchronous on rk3288, then sync 
revoked.
So we need to enable clocks of all devices.

>>>> +               clk = of_clk_get(node, i);
>>>> +               if (IS_ERR(clk)) {
>>>> +                       error = PTR_ERR(clk);
>>>> +                       dev_err(pmu->dev,
>>>> +                               "%s: failed to get clk %s (index %d):
>>>> %d\n",
>>>> +                               node->name, __clk_get_name(clk), i,
>>>> error);
>>>> +                       goto err_out;
>>>> +               }
>>>> +
>>>> +               error = clk_prepare(clk);
>>>> +               if (error) {
>>>> +                       dev_err(pmu->dev,
>>>> +                               "%s: failed to prepare clk %s (index %d):
>>>> %d\n",
>>>> +                               node->name, __clk_get_name(clk), i,
>>>> error);
>>>> +                       clk_put(clk);
>>>> +                       goto err_out;
>>>> +               }
>>>> +
>>>> +               pd->clks[pd->num_clks++] = clk;
>>>> +
>>>> +               dev_dbg(pmu->dev, "added clock '%s' to domain '%s'\n",
>>>> +                       __clk_get_name(clk), node->name);
>>>> +       }
>>>> +
>>>> +       error = rockchip_pd_power(pd, true);
>>>> +       if (error) {
>>>> +               dev_err(pmu->dev,
>>>> +                       "failed to power on domain '%s': %d\n",
>>>> +                       node->name, error);
>>>> +               goto err_out;
>>>> +       }
>>>> +
>>>> +       pd->genpd.name = node->name;
>>>> +       pd->genpd.power_off = rockchip_pd_power_off;
>>>> +       pd->genpd.power_on = rockchip_pd_power_on;
>>>> +       pd->genpd.attach_dev = rockchip_pd_attach_dev;
>>>> +       pd->genpd.detach_dev = rockchip_pd_detach_dev;
>>>> +       pd->genpd.dev_ops.start = rockchip_pd_start_dev;
>>>> +       pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;
>>> Instead of assigning the ->stop|start() callbacks, which do
>>> pm_clk_suspend|resume(), just set the genpd->flags to
>>> GENPD_FLAG_PM_CLK, and genpd will fix this for you.
>>>
>> Ditto.
> Again, I don't follow. Here is what goes on:
>
> rockchip_pd_start_dev() calls pm_clk_resume() and
> rockchip_pd_stop_dev() calls pm_clk_suspend().
> Instead of assigning the below callbacks...
>
> pd->genpd.dev_ops.start = rockchip_pd_start_dev;
> pd->genpd.dev_ops.stop = rockchip_pd_stop_dev;
>
> ... just use GENPD_FLAG_PM_CLK and let genpd deal with the calls to
> pm_clk_suspend|resume().

Yes, you are right.
Done, fixed in next patch v16.

Thanks!

Caesar
>>
>>>> +       pm_genpd_init(&pd->genpd, NULL, false);
>>>> +
>>>> +       pmu->genpd_data.domains[id] = &pd->genpd;
>>>> +       return 0;
>>>> +
>>>> +err_out:
>>>> +       while (--i >= 0) {
>>>> +               clk_unprepare(pd->clks[i]);
>>>> +               clk_put(pd->clks[i]);
>>>> +       }
>>>> +       return error;
>>>> +}
>>>> +
> [...]
>
> Kind regards
> Uffe
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip



From heiko at sntech.de  Mon Jun 29 05:31:17 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 29 Jun 2015 14:31:17 +0200
Subject: [PATCH v2 0/4] arm64: add initial support for the Rockchip rk3368
Message-ID: <3333434.ZKWQ6GxgtB@diego>

This adds initial support for the new rk3368 ARM64 soc from Rockchip.

Overall it looks like someone dropped some A53 cores into a rk3288, so
it shares a lot of peripherals that only differ in details. Therefore
stuff like the mmc, usb, spi, i2c controllers work out of the box.
The support for the gmac already made it into the merge window as well
as the pinctrl support.

Interestingly, in its core the rk3368 seems trying to be a model student
with psci for smp and using scpi for ddr frequency scaling, although I
currently do not understand how the mailbox works yet. The display
controllers also are only minimally different so I'm hopefully to have
working graphics in the near-ish future :-)


As mentioned in the dts patch, this series depends on the dt-binding
header for the clock ids, so will need a shared branch once this is ready.

changes since v1:
- add missing device_type = "memeory", as found by Mark Rutland
- fix patch subject for patch4 (the board is called R88),
  found by Naoki Fukaumi

Heiko Stuebner (4):
  arm64: add Rockchip architecture entry
  arm64: defconfig: enable ARCH_ROCKCHIP
  arm64: dts: add Rockchip rk3368 core dtsi and board dts for the r88
    board
  dt-bindings: document rk3368 R89 board from Rockchip

 Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
 arch/arm64/Kconfig                                 |  10 +
 arch/arm64/boot/dts/Makefile                       |   1 +
 arch/arm64/boot/dts/rockchip/Makefile              |   5 +
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts        | 353 ++++++++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi           | 900 +++++++++++++++++++++
 arch/arm64/configs/defconfig                       |   2 +
 7 files changed, 1275 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi

-- 
2.1.4




From heiko at sntech.de  Mon Jun 29 05:31:54 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 29 Jun 2015 14:31:54 +0200
Subject: [PATCH v2 1/4] arm64: add Rockchip architecture entry
In-Reply-To: <3333434.ZKWQ6GxgtB@diego>
References: <3333434.ZKWQ6GxgtB@diego>
Message-ID: <1507422.Ta3AHj4ijV@diego>

The rk3368 is Rockchip's first ARM64 soc, build around 8 Cortex-A53 cores.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/Kconfig | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 290ed64..9af528a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -197,6 +197,16 @@ config ARCH_QCOM
 	help
 	  This enables support for the ARMv8 based Qualcomm chipsets.
 
+config ARCH_ROCKCHIP
+	bool "Rockchip Platforms"
+	select ARCH_HAS_RESET_CONTROLLER
+	select ARCH_REQUIRE_GPIOLIB
+	select PINCTRL
+	select PINCTRL_ROCKCHIP
+	help
+	  This enables support for the ARMv8 based Rockchip chipsets,
+	  like the RK3368.
+
 config ARCH_SEATTLE
 	bool "AMD Seattle SoC Family"
 	help
-- 
2.1.4




From heiko at sntech.de  Mon Jun 29 05:32:20 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 29 Jun 2015 14:32:20 +0200
Subject: [PATCH v2 2/4] arm64: defconfig: enable ARCH_ROCKCHIP
In-Reply-To: <3333434.ZKWQ6GxgtB@diego>
References: <3333434.ZKWQ6GxgtB@diego>
Message-ID: <1894031.Obs8fLraqt@diego>

Enable building Rockchip support in the defconfig.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
 arch/arm64/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index daefbf0..77bc5bc 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -34,6 +34,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_EXYNOS7=y
 CONFIG_ARCH_FSL_LS2085A=y
 CONFIG_ARCH_MEDIATEK=y
+CONFIG_ARCH_ROCKCHIP=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_TEGRA_132_SOC=y
@@ -99,6 +100,7 @@ CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-- 
2.1.4




From heiko at sntech.de  Mon Jun 29 05:34:35 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 29 Jun 2015 14:34:35 +0200
Subject: [PATCH v2 3/4] arm64: dts: add Rockchip rk3368 core dtsi and board
 dts for the r88 board
In-Reply-To: <3333434.ZKWQ6GxgtB@diego>
References: <3333434.ZKWQ6GxgtB@diego>
Message-ID: <4392776.GZArrLSWTI@diego>

In terms of peripherals the rk3368 is quite similar to the rk3288, which
makes it possible to have a lot basic components working in the first go.
More to follow once I tracked down all the tiny differences that still
exist in some parts.

With these dts files, the R88 board is able to boot from an attached
usb device and most likely from its emmc too, if the emmc uses a standard
partition table instead of Rockchip's own one - the emmc itself is
detected correctly.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
This of course needs the dt-binding header from clock series, so
a shared branch will be needed.

 arch/arm64/boot/dts/Makefile                |   1 +
 arch/arm64/boot/dts/rockchip/Makefile       |   5 +
 arch/arm64/boot/dts/rockchip/rk3368-r88.dts | 353 +++++++++++
 arch/arm64/boot/dts/rockchip/rk3368.dtsi    | 900 ++++++++++++++++++++++++++++
 4 files changed, 1259 insertions(+)
 create mode 100644 arch/arm64/boot/dts/rockchip/Makefile
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368-r88.dts
 create mode 100644 arch/arm64/boot/dts/rockchip/rk3368.dtsi

diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index ad26a75..6916eec 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -6,6 +6,7 @@ dts-dirs += exynos
 dts-dirs += freescale
 dts-dirs += mediatek
 dts-dirs += qcom
+dts-dirs += rockchip
 dts-dirs += sprd
 dts-dirs += xilinx
 
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
new file mode 100644
index 0000000..601e6a2
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff --git a/arch/arm64/boot/dts/rockchip/rk3368-r88.dts b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
new file mode 100644
index 0000000..d0c519b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368-r88.dts
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+
+/ {
+	model = "Rockchip R88";
+	compatible = "rockchip,r88", "rockchip,rk3368";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		pinctrl-0 = <&emmc_reset>;
+		pinctrl-names = "default";
+		reset-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+	};
+
+	keys: gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_key>;
+
+		button at 0 {
+			gpio-key,wakeup = <1>;
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			label = "GPIO Power";
+			linux,code = <116>;
+		};
+	};
+
+	leds: gpio-leds {
+		compatible = "gpio-leds";
+
+		work {
+			gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
+			label = "r88:green:led";
+			pinctrl-names = "default";
+			pinctrl-0 = <&led_ctl>;
+		};
+	};
+
+	ir: ir-receiver {
+		compatible = "gpio-ir-receiver";
+		gpios = <&gpio3 30 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ir_int>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&hym8563>;
+		clock-names = "ext_clock";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bt_rst>, <&wifi_reg_on>;
+
+		reset-gpios =
+			/* BT_RST_N */
+			<&gpio3 5 GPIO_ACTIVE_LOW>,
+
+			/* WL_REG_ON */
+			<&gpio3 4 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc_18: vcc18-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_18";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	/* supplies both host and otg */
+	vcc_host: vcc-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&host_vbus_drv>;
+		regulator-name = "vcc_host";
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_io: vcc-io-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	vcc_lan: vcc-lan-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_lan";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vccio_wl: vccio-wl-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vccio_wl";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_io>;
+	};
+
+	vdd_10: vdd-10-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_10";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+};
+
+&emmc {
+	broken-cd;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	mmc-pwrseq = <&emmc_pwrseq>;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+	status = "okay";
+};
+
+&gmac {
+	phy-supply = <&vcc_lan>;
+	phy-mode = "rmii";
+	clock_in_out = "output";
+	snps,reset-gpio = <&gpio3 12 0>;
+	snps,reset-active-low;
+	snps,reset-delays-us = <0 10000 1000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&rmii_pins>;
+	tx_delay = <0x30>;
+	rx_delay = <0x10>;
+	status = "ok";
+};
+
+&i2c0 {
+	status = "okay";
+
+	vdd_cpu: syr827 at 40 {
+		compatible = "silergy,syr827";
+		reg = <0x40>;
+		fcs,suspend-voltage-selector = <1>;
+		regulator-name = "vdd_cpu";
+		regulator-enable-ramp-delay = <300>;
+		regulator-min-microvolt = <712500>;
+		regulator-max-microvolt = <1500000>;
+		regulator-ramp-delay = <8000>;
+		regulator-always-on;
+		regulator-boot-on;
+		vin-supply = <&vcc_sys>;
+	};
+
+	hym8563: hym8563 at 51 {
+		compatible = "haoyu,hym8563";
+		reg = <0x51>;
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		clock-output-names = "xin32k";
+		/* rtc_int is not connected */
+	};
+};
+
+&sdio0 {
+	assigned-clocks = <&cru SCLK_SDIO0>;
+	assigned-clock-parents = <&cru PLL_CPLL>;
+	broken-cd;
+	bus-width = <4>;
+	cap-sd-highspeed;
+	cap-sdio-irq;
+	keep-power-in-suspend;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdio0_clk &sdio0_cmd &sdio0_bus4>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vccio_wl>;
+	status = "okay";
+};
+
+&pinctrl {
+	pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+		bias-disable;
+		drive-strength = <8>;
+	};
+
+	pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+		bias-pull-up;
+		drive-strength = <8>;
+	};
+
+	emmc {
+		emmc_bus8: emmc-bus8 {
+			rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 19 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 20 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 21 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 22 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 23 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 24 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
+					<1 25 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+		};
+
+		emmc-clk {
+			rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+		};
+
+		emmc-cmd {
+			rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
+		};
+
+		emmc_reset: emmc-reset {
+			rockchip,pins = <2 3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	ir {
+		ir_int: ir-int {
+			rockchip,pins = <3 30 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	keys {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
+	leds {
+		stby_pwren: stby-pwren {
+			rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		led_ctl: led-ctl {
+			rockchip,pins = <3 29 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	sdio {
+		wifi_reg_on: wifi-reg-on {
+			rockchip,pins = <3 4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+
+		bt_rst: bt-rst {
+			rockchip,pins = <3 5 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 4 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&saradc {
+	vref-supply = <&vcc_18>;
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "host";
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
new file mode 100644
index 0000000..a712bea
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -0,0 +1,900 @@
+/*
+ * Copyright (c) 2015 Heiko Stuebner <heiko at sntech.de>
+ *
+ * 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 library 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 library 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.
+ */
+
+#include <dt-bindings/clock/rk3368-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+/ {
+	compatible = "rockchip,rk3368";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		serial4 = &uart4;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu_b0>;
+				};
+				core1 {
+					cpu = <&cpu_b1>;
+				};
+				core2 {
+					cpu = <&cpu_b2>;
+				};
+				core3 {
+					cpu = <&cpu_b3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu_l0>;
+				};
+				core1 {
+					cpu = <&cpu_l1>;
+				};
+				core2 {
+					cpu = <&cpu_l2>;
+				};
+				core3 {
+					cpu = <&cpu_l3>;
+				};
+			};
+		};
+
+		idle-states {
+			entry-method = "arm,psci";
+
+			cpu_sleep: cpu-sleep-0 {
+				compatible = "arm,idle-state";
+				arm,psci-suspend-param = <0x1010000>;
+				entry-latency-us = <0x3fffffff>;
+				exit-latency-us = <0x40000000>;
+				min-residency-us = <0xffffffff>;
+			};
+		};
+
+		cpu_l0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_l3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b0: cpu at 100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x100>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b1: cpu at 101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x101>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b2: cpu at 102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x102>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+
+		cpu_b3: cpu at 103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x103>;
+			cpu-idle-states = <&cpu_sleep>;
+			enable-method = "psci";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu_l0>, <&cpu_l1>, <&cpu_l2>,
+				     <&cpu_l3>, <&cpu_b0>, <&cpu_b1>,
+				     <&cpu_b2>, <&cpu_b3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	sdmmc: dwmmc at ff0c0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0c0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	sdio0: dwmmc at ff0d0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0d0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
+			 <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	emmc: dwmmc at ff0f0000 {
+		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
+		reg = <0x0 0xff0f0000 0x0 0x4000>;
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	saradc: saradc at ff100000 {
+		compatible = "rockchip,saradc";
+		reg = <0x0 0xff100000 0x0 0x100>;
+		interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+		#io-channel-cells = <1>;
+		clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+		clock-names = "saradc", "apb_pclk";
+		status = "disabled";
+	};
+
+	spi0: spi at ff110000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff110000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi1: spi at ff120000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff120000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi2: spi at ff130000 {
+		compatible = "rockchip,rk3368-spi", "rockchip,rk3066-spi";
+		reg = <0x0 0xff130000 0x0 0x1000>;
+		clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+		clock-names = "spiclk", "apb_pclk";
+		interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c1: i2c at ff140000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff140000 0x0 0x1000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C1>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c1_xfer>;
+		status = "disabled";
+	};
+
+	i2c3: i2c at ff150000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff150000 0x0 0x1000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C3>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c3_xfer>;
+		status = "disabled";
+	};
+
+	i2c4: i2c at ff160000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff160000 0x0 0x1000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C4>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c4_xfer>;
+		status = "disabled";
+	};
+
+	i2c5: i2c at ff170000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff170000 0x0 0x1000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C5>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c5_xfer>;
+		status = "disabled";
+	};
+
+	uart0: serial at ff180000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff180000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart1: serial at ff190000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff190000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart3: serial at ff1b0000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1b0000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	uart4: serial at ff1c0000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff1c0000 0x0 0x100>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	gmac: ethernet at ff290000 {
+		compatible = "rockchip,rk3368-gmac";
+		reg = <0x0 0xff290000 0x0 0x10000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "macirq";
+		rockchip,grf = <&grf>;
+		clocks = <&cru SCLK_MAC>,
+			<&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>,
+			<&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>,
+			<&cru ACLK_GMAC>, <&cru PCLK_GMAC>;
+		clock-names = "stmmaceth",
+			"mac_clk_rx", "mac_clk_tx",
+			"clk_mac_ref", "clk_mac_refout",
+			"aclk_mac", "pclk_mac";
+		status = "disabled";
+	};
+
+	usb_host0_ehci: usb at ff500000 {
+		compatible = "generic-ehci";
+		reg = <0x0 0xff500000 0x0 0x100>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_HOST0>;
+		clock-names = "usbhost";
+		status = "disabled";
+	};
+
+	usb_otg: usb at ff580000 {
+		compatible = "rockchip,rk3368-usb", "rockchip,rk3066-usb",
+				"snps,dwc2";
+		reg = <0x0 0xff580000 0x0 0x40000>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru HCLK_OTG0>;
+		clock-names = "otg";
+		dr_mode = "otg";
+		g-np-tx-fifo-size = <16>;
+		g-rx-fifo-size = <275>;
+		g-tx-fifo-size = <256 128 128 64 64 32>;
+		g-use-dma;
+		status = "disabled";
+	};
+
+	i2c0: i2c at ff650000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff650000 0x0 0x1000>;
+		clocks = <&cru PCLK_I2C0>;
+		clock-names = "i2c";
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c0_xfer>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	i2c2: i2c at ff660000 {
+		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
+		reg = <0x0 0xff660000 0x0 0x1000>;
+		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clock-names = "i2c";
+		clocks = <&cru PCLK_I2C2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c2_xfer>;
+		status = "disabled";
+	};
+
+	uart2: serial at ff690000 {
+		compatible = "rockchip,rk3368-uart", "snps,dw-apb-uart";
+		reg = <0x0 0xff690000 0x0 0x100>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2_xfer>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		status = "disabled";
+	};
+
+	pmugrf: syscon at ff738000 {
+		compatible = "rockchip,rk3368-pmugrf", "syscon";
+		reg = <0x0 0xff738000 0x0 0x1000>;
+	};
+
+	cru: clock-controller at ff760000 {
+		compatible = "rockchip,rk3368-cru";
+		reg = <0x0 0xff760000 0x0 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	grf: syscon at ff770000 {
+		compatible = "rockchip,rk3368-grf", "syscon";
+		reg = <0x0 0xff770000 0x0 0x1000>;
+	};
+
+	wdt: watchdog at ff800000 {
+		compatible = "rockchip,rk3368-wdt", "snps,dw-wdt";
+		reg = <0x0 0xff800000 0x0 0x100>;
+		clocks = <&cru PCLK_WDT>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller at ffb71000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0x0 0xffb71000 0x0 0x1000>,
+		      <0x0 0xffb72000 0x0 0x1000>,
+		      <0x0 0xffb74000 0x0 0x2000>,
+		      <0x0 0xffb76000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9
+		      (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk3368-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <0x2>;
+		#size-cells = <0x2>;
+		ranges;
+
+		gpio0: gpio0 at ff750000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff750000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO0>;
+			interrupts = <GIC_SPI 0x51 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio1: gpio1 at ff780000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff780000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO1>;
+			interrupts = <GIC_SPI 0x52 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio2: gpio2 at ff790000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff790000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO2>;
+			interrupts = <GIC_SPI 0x53 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		gpio3: gpio3 at ff7a0000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x0 0xff7a0000 0x0 0x100>;
+			clocks = <&cru PCLK_GPIO3>;
+			interrupts = <GIC_SPI 0x54 IRQ_TYPE_LEVEL_HIGH>;
+
+			gpio-controller;
+			#gpio-cells = <0x2>;
+
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		emmc {
+			emmc_clk: emmc-clk {
+				rockchip,pins = <2 4 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			emmc_cmd: emmc-cmd {
+				rockchip,pins = <1 26 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_pwr: emmc-pwr {
+				rockchip,pins = <1 27 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus1: emmc-bus1 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus4: emmc-bus4 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
+						<1 19 RK_FUNC_2 &pcfg_pull_up>,
+						<1 20 RK_FUNC_2 &pcfg_pull_up>,
+						<1 21 RK_FUNC_2 &pcfg_pull_up>;
+			};
+
+			emmc_bus8: emmc-bus8 {
+				rockchip,pins = <1 18 RK_FUNC_2 &pcfg_pull_up>,
+						<1 19 RK_FUNC_2 &pcfg_pull_up>,
+						<1 20 RK_FUNC_2 &pcfg_pull_up>,
+						<1 21 RK_FUNC_2 &pcfg_pull_up>,
+						<1 22 RK_FUNC_2 &pcfg_pull_up>,
+						<1 23 RK_FUNC_2 &pcfg_pull_up>,
+						<1 24 RK_FUNC_2 &pcfg_pull_up>,
+						<1 25 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		gmac {
+			rgmii_pins: rgmii-pins {
+				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
+						<3 24 RK_FUNC_1 &pcfg_pull_none>,
+						<3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 10 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 14 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 28 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 15 RK_FUNC_1 &pcfg_pull_none>,
+						<3 16 RK_FUNC_1 &pcfg_pull_none>,
+						<3 17 RK_FUNC_1 &pcfg_pull_none>,
+						<3 18 RK_FUNC_1 &pcfg_pull_none>,
+						<3 25 RK_FUNC_1 &pcfg_pull_none>,
+						<3 20 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			rmii_pins: rmii-pins {
+				rockchip,pins =	<3 22 RK_FUNC_1 &pcfg_pull_none>,
+						<3 24 RK_FUNC_1 &pcfg_pull_none>,
+						<3 19 RK_FUNC_1 &pcfg_pull_none>,
+						<3 8 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 9 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 13 RK_FUNC_1 &pcfg_pull_none_12ma>,
+						<3 15 RK_FUNC_1 &pcfg_pull_none>,
+						<3 16 RK_FUNC_1 &pcfg_pull_none>,
+						<3 20 RK_FUNC_1 &pcfg_pull_none>,
+						<3 21 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c0 {
+			i2c0_xfer: i2c0-xfer {
+				rockchip,pins = <0 6 RK_FUNC_1 &pcfg_pull_none>,
+						<0 7 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <2 21 RK_FUNC_1 &pcfg_pull_none>,
+						<2 22 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c2 {
+			i2c2_xfer: i2c2-xfer {
+				rockchip,pins = <0 9 RK_FUNC_2 &pcfg_pull_none>,
+						<3 31 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <1 16 RK_FUNC_1 &pcfg_pull_none>,
+						<1 17 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		i2c4 {
+			i2c4_xfer: i2c4-xfer {
+				rockchip,pins = <3 24 RK_FUNC_2 &pcfg_pull_none>,
+						<3 25 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		i2c5 {
+			i2c5_xfer: i2c5-xfer {
+				rockchip,pins = <3 26 RK_FUNC_2 &pcfg_pull_none>,
+						<3 27 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		sdio0 {
+			sdio0_bus1: sdio0-bus1 {
+				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bus4: sdio0-bus4 {
+				rockchip,pins = <2 28 RK_FUNC_1 &pcfg_pull_up>,
+						<2 29 RK_FUNC_1 &pcfg_pull_up>,
+						<2 30 RK_FUNC_1 &pcfg_pull_up>,
+						<2 31 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_cmd: sdio0-cmd {
+				rockchip,pins = <3 0 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_clk: sdio0-clk {
+				rockchip,pins = <3 1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdio0_cd: sdio0-cd {
+				rockchip,pins = <3 2 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_wp: sdio0-wp {
+				rockchip,pins = <3 3 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_pwr: sdio0-pwr {
+				rockchip,pins = <3 4 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_bkpwr: sdio0-bkpwr {
+				rockchip,pins = <3 5 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdio0_int: sdio0-int {
+				rockchip,pins = <3 6 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins = <2 9 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins = <2 10 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_cd: sdmcc-cd {
+				rockchip,pins = <2 11 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins = <2 5 RK_FUNC_1 &pcfg_pull_up>,
+						<2 6 RK_FUNC_1 &pcfg_pull_up>,
+						<2 7 RK_FUNC_1 &pcfg_pull_up>,
+						<2 8 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		spi0 {
+			spi0_clk: spi0-clk {
+				rockchip,pins = <1 29 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi0_cs0: spi0-cs0 {
+				rockchip,pins = <1 24 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_cs1: spi0-cs1 {
+				rockchip,pins = <1 25 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_tx: spi0-tx {
+				rockchip,pins = <1 23 RK_FUNC_3 &pcfg_pull_up>;
+			};
+			spi0_rx: spi0-rx {
+				rockchip,pins = <1 22 RK_FUNC_3 &pcfg_pull_up>;
+			};
+		};
+
+		spi1 {
+			spi1_clk: spi1-clk {
+				rockchip,pins = <1 14 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs0: spi1-cs0 {
+				rockchip,pins = <1 15 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_cs1: spi1-cs1 {
+				rockchip,pins = <3 28 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_rx: spi1-rx {
+				rockchip,pins = <1 16 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi1_tx: spi1-tx {
+				rockchip,pins = <1 17 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		spi2 {
+			spi2_clk: spi2-clk {
+				rockchip,pins = <0 12 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_cs0: spi2-cs0 {
+				rockchip,pins = <0 13 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_rx: spi2-rx {
+				rockchip,pins = <0 10 RK_FUNC_2 &pcfg_pull_up>;
+			};
+			spi2_tx: spi2-tx {
+				rockchip,pins = <0 11 RK_FUNC_2 &pcfg_pull_up>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <2 24 RK_FUNC_1 &pcfg_pull_up>,
+						<2 25 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <2 26 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <2 27 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <0 20 RK_FUNC_3 &pcfg_pull_up>,
+						<0 21 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <0 22 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <0 23 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+
+		uart2 {
+			uart2_xfer: uart2-xfer {
+				rockchip,pins = <2 6 RK_FUNC_2 &pcfg_pull_up>,
+						<2 5 RK_FUNC_2 &pcfg_pull_none>;
+			};
+			/* no rts / cts for uart2 */
+		};
+
+		uart3 {
+			uart3_xfer: uart3-xfer {
+				rockchip,pins = <3 29 RK_FUNC_2 &pcfg_pull_up>,
+						<3 30 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart3_cts: uart3-cts {
+				rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			uart3_rts: uart3-rts {
+				rockchip,pins = <3 17 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart4 {
+			uart4_xfer: uart4-xfer {
+				rockchip,pins = <0 27 RK_FUNC_3 &pcfg_pull_up>,
+						<0 26 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart4_cts: uart4-cts {
+				rockchip,pins = <0 24 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			uart4_rts: uart4-rts {
+				rockchip,pins = <0 25 RK_FUNC_3 &pcfg_pull_none>;
+			};
+		};
+	};
+};
-- 
2.1.4




From heiko at sntech.de  Mon Jun 29 05:35:13 2015
From: heiko at sntech.de (Heiko =?ISO-8859-1?Q?St=FCbner?=)
Date: Mon, 29 Jun 2015 14:35:13 +0200
Subject: [PATCH v2 4/4] dt-bindings: document rk3368 R88 board from Rockchip
In-Reply-To: <3333434.ZKWQ6GxgtB@diego>
References: <3333434.ZKWQ6GxgtB@diego>
Message-ID: <7253030.KcEv5ApOSe@diego>

The initial board containing the rk3368 ARM64 soc.

Signed-off-by: Heiko Stuebner <heiko at sntech.de>
---
This should probably be simply in one branch with the Netxeon board
seen in the diff above, to prevent unncessary merge conflicts?

 Documentation/devicetree/bindings/arm/rockchip.txt | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index b30bed1..c4119e0 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -30,3 +30,7 @@ Rockchip platforms device tree bindings
 - Netxeon R89 board:
     Required root node properties:
       - compatible = "netxeon,r89", "rockchip,rk3288";
+
+- Rockchip R88 board:
+    Required root node properties:
+      - compatible = "rockchip,r88", "rockchip,rk3368";
-- 
2.1.4




From mark.yao at rock-chips.com  Mon Jun 29 23:50:59 2015
From: mark.yao at rock-chips.com (Mark yao)
Date: Tue, 30 Jun 2015 14:50:59 +0800
Subject: [GIT PULL] drm/rockchip: fixes and new features
Message-ID: <55923C53.4020305@rock-chips.com>

Hi Dave.

     Some fixes and some new features. I'd like you can pull them.

The following changes since commit c5fd936e992dd2829167d2adc63e151675ca6898:

   drm/nouveau: Pause between setting gpu to D3hot and cutting the power 
(2015-06-26 10:26:37 +1000)

are available in the git repository at:

   https://github.com/markyzq/kernel-drm-rockchip.git 
drm-rockchip-2015-06-30

for you to fetch changes up to 5295c05eb30d743987172853179333c80b8242bc:

   drm/rockchip: default enable win2/3 area0 bit (2015-06-30 14:24:10 +0800)

----------------------------------------------------------------
Heiko St?bner (1):
       drm/rockchip: only call drm_fb_helper_hotplug_event if fb_helper 
present

Mark Yao (6):
       drm/rockchip: import dma_buf to gem
       drm/rockchip: vop: optimize virtual stride calculate
       drm/rockchip: vop: fix yuv plane support
       drm/rockchip: vop: support plane scale
       drm/rockchip: vop: switch cursor plane to window 3
       drm/rockchip: default enable win2/3 area0 bit

Tomasz Figa (1):
       drm/rockchip: Add BGR formats to VOP

  drivers/gpu/drm/rockchip/rockchip_drm_drv.c |    1 +
  drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |    3 +-
  drivers/gpu/drm/rockchip/rockchip_drm_gem.c |   40 ++-
  drivers/gpu/drm/rockchip/rockchip_drm_gem.h |    5 +-
  drivers/gpu/drm/rockchip/rockchip_drm_vop.c |  500 
++++++++++++++++++++++++++-
  drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   96 +++++
  6 files changed, 628 insertions(+), 17 deletions(-)

-- 
?ark




From klimov.linux at gmail.com  Tue Jun 30 11:03:58 2015
From: klimov.linux at gmail.com (Alexey Klimov)
Date: Tue, 30 Jun 2015 21:03:58 +0300
Subject: [PATCH 1/2] spi/s3c24xx: remove unnecessary memset of s3c24xx_spi
Message-ID: <1435687438.27701.12.camel@ceres>

Memory for this struct is allocated by spi_alloc_master() using
kzalloc() so it doesn't need to be set to 0 one more time.

Signed-off-by: Alexey Klimov <klimov.linux at gmail.com>
---
 drivers/spi/spi-s3c24xx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
index f747ca2..f36bc32 100644
--- a/drivers/spi/spi-s3c24xx.c
+++ b/drivers/spi/spi-s3c24xx.c
@@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
 	}
 
 	hw = spi_master_get_devdata(master);
-	memset(hw, 0, sizeof(struct s3c24xx_spi));
 
 	hw->master = master;
 	hw->pdata = pdata = dev_get_platdata(&pdev->dev);
-- 
1.9.1





From klimov.linux at gmail.com  Tue Jun 30 11:04:07 2015
From: klimov.linux at gmail.com (Alexey Klimov)
Date: Tue, 30 Jun 2015 21:04:07 +0300
Subject: [PATCH 2/2] spi/rockchip: remove unnecessary memset of rockchip_spi
Message-ID: <1435687447.27701.13.camel@ceres>

Memory for struct rockchip_spi is allocated by spi_alloc_master()
using kzalloc() so it doesn't need to be set to 0 one more time.

Signed-off-by: Alexey Klimov <klimov.linux at gmail.com>
---
 drivers/spi/spi-rockchip.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 68e7efe..79a8bc4 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -645,7 +645,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	rs = spi_master_get_devdata(master);
-	memset(rs, 0, sizeof(struct rockchip_spi));
 
 	/* Get basic io resource and map it */
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.9.1





From djkurtz at chromium.org  Tue Jun 30 21:25:44 2015
From: djkurtz at chromium.org (Daniel Kurtz)
Date: Wed, 1 Jul 2015 12:25:44 +0800
Subject: [PATCH 1/2] spi/s3c24xx: remove unnecessary memset of s3c24xx_spi
In-Reply-To: <1435687438.27701.12.camel@ceres>
References: <1435687438.27701.12.camel@ceres>
Message-ID: <CAGS+omAnwhxKzfBm18oETgCKM2r3qtVpS9VR=GzbQhU6ujzVrQ@mail.gmail.com>

On Wed, Jul 1, 2015 at 2:03 AM, Alexey Klimov <klimov.linux at gmail.com> wrote:
> Memory for this struct is allocated by spi_alloc_master() using
> kzalloc() so it doesn't need to be set to 0 one more time.
>
> Signed-off-by: Alexey Klimov <klimov.linux at gmail.com>

Yup, I just noticed this too when reviewing the mediatek SPI driver.

For both patches:
Reviewed-by: Daniel Kurtz <djkurtz at chromium.org>

> ---
>  drivers/spi/spi-s3c24xx.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c
> index f747ca2..f36bc32 100644
> --- a/drivers/spi/spi-s3c24xx.c
> +++ b/drivers/spi/spi-s3c24xx.c
> @@ -501,7 +501,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)
>         }
>
>         hw = spi_master_get_devdata(master);
> -       memset(hw, 0, sizeof(struct s3c24xx_spi));
>
>         hw->master = master;
>         hw->pdata = pdata = dev_get_platdata(&pdev->dev);
> --
> 1.9.1
>
>
>
>
> _______________________________________________
> Linux-rockchip mailing list
> Linux-rockchip at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


